Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: ahoward/dao
base: 07bd2e1911
...
head fork: ahoward/dao
compare: 5fbf1b9648
  • 2 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
Commits on Apr 07, 2012
@ahoward moar tests 359e416
Commits on Apr 08, 2012
@ahoward mo betta teh mount. tests for mount/upload. 5fbf1b9
View
65 lib/dao/conducer.rb
@@ -107,7 +107,7 @@ def Conducer.new(*args, &block)
def init(*args, &block)
controllers, args = args.partition{|arg| arg.is_a?(ActionController::Base)}
actions, args = args.partition{|arg| arg.is_a?(Action)}
- models, args = args.partition{|arg| arg.respond_to?(:new_record?) }
+ models, args = args.partition{|arg| arg.respond_to?(:persisted?) }
hashes, args = args.partition{|arg| arg.is_a?(Hash)}
@name = self.class.model_name.singular.sub(/_+$/, '')
@@ -146,6 +146,8 @@ def initialize(*args, &block)
def default_initialize(*args, &block)
update_models()
+ update_mounted()
+
initialize_for_action(*args, &block)
update_attributes(params)
@@ -167,6 +169,13 @@ def update_models(*models)
end
end
+ def update_mounted(list = [])
+ list = self.class.mounted if list.empty?
+ list.each do |args, block|
+ mount(*args, &block)
+ end
+ end
+
def model_key_for(model)
case model
when String
@@ -218,27 +227,17 @@ def update_attributes(*args, &block)
params = Map.new(params)
- (@setting ||= []).push(params)
- recursion_depth = @setting.size - 1
-
- begin
- Dao.tree_walk(params) do |key, value|
- unless recursion_depth > 0
- if respond_to?(:_update_attributes) and send(:_update_attributes, key => value)
- throw(:tree_walk, :next_sibling)
- end
+ @attributes.set(params)
- if((handler = @attributes.get(key)).respond_to?(:_update_attributes))
- handler._update_attributes(:value => value)
- throw(:tree_walk, :next_sibling)
- end
- end
+ deepest_first = mounted.sort_by{|mnt| mnt._key.size}.reverse
- @attributes.set(key, value)
- end
- ensure
- @setting.pop
+ deepest_first.each do |mnt|
+ value = @attributes.get(mnt._key)
+ mnt._set(value)
+ @attributes.set(mnt._key => mnt)
end
+
+ @attributes
end
def attributes=(attributes)
@@ -348,6 +347,12 @@ def model?(object)
##
#
def save
+ default_save
+ end
+
+ def default_save
+ return false unless valid?
+
if @model
attributes = self.attributes.dup
@@ -357,9 +362,14 @@ def save
attributes.delete(key)
end
+ mounted.each do |mnt|
+ attributes.set(mnt._key, mnt._value)
+ end
+
@model.update_attributes(attributes)
if @model.save
+ mounted.each{|mnt| mnt._clear}
return true
else
errors.relay(@model.errors)
@@ -391,7 +401,22 @@ def destroy!
## misc
#
def mount(object, *args, &block)
- object.mount(self, *args, &block)
+ mounted = object.mount(self, *args, &block)
+ ensure
+ Dao.ensure_interface!(mounted, :_set, :_key, :_value, :_clear)
+ self.mounted.push(mounted)
+ end
+
+ def mounted
+ @mounted ||= []
+ end
+
+ def self.mount(*args, &block)
+ mounted.push([args, block])
+ end
+
+ def self.mounted
+ @mounted ||= []
end
def key_for(key)
View
116 lib/dao/rails/lib/generators/dao/templates/dao_helper.rb
@@ -1,46 +1,9 @@
# -*- encoding : utf-8 -*-
module DaoHelper
- def render_dao(result, *args, &block)
- if result.status =~ 200 or result.status == 420
- @result = result unless defined?(@result)
- render(*args, &block)
- else
- result.error!
- end
- end
-
- def dao(path, *args, &block)
- options = args.extract_options!.to_options!
-
- mode = options[:mode]
-
- if mode.blank?
- mode =
- case request.method
- when "GET"
- :read
- when "PUT", "POST", "DELETE"
- :write
- else
- :read
- end
- end
-
- @dao = api.send(mode, path, params)
- @dao.route = request.fullpath
- #@dao.mode = mode
-
- #unless options[:error!] == false
- @dao.error! unless @dao.status.ok?
- #end
-
- block ? block.call(@dao) : @dao
- end
-
def dao_form_for(*args, &block)
options = args.extract_options!.to_options!
- model = args.flatten.select{|arg| arg.respond_to?(:new_record?)}.last
+ model = args.flatten.detect{|arg| arg.respond_to?(:persisted?)}
if model
first = args.shift
@@ -51,46 +14,6 @@ def dao_form_for(*args, &block)
options.clear
- url ||= url_for(first)
-
- if model.persisted?
- method ||= :put
- else
- method ||= :post
- end
-
- options[:url] = url
- options[:html] = html.dup.merge(:method => method)
-
- args.push(model)
- args.push(options)
-
- form_for(*args) do
- block.call(model.form)
- end
- else
- args.push(request.fullpath) if args.empty?
- args.push(dao_form_attrs(options))
- form_tag(*args, &block)
- end
- end
-
- def dao_form_for(*args, &block)
- options = args.extract_options!.to_options!
-
- model = args.flatten.select{|arg| arg.respond_to?(:new_record?)}.last
-
- if model
- first = args.shift
- url = args.shift || options.delete(:url)
-
- method = options.delete(:method)
- html = dao_form_attrs(options)
-
- options.clear
-
- #url ||= url_for(first)
-
if model.persisted?
method ||= :put
else
@@ -138,5 +61,42 @@ def dao_form_attrs(*args)
options[:enctype] ||= "multipart/form-data"
options
end
+
+ def render_dao(result, *args, &block)
+ if result.status =~ 200 or result.status == 420
+ @result = result unless defined?(@result)
+ render(*args, &block)
+ else
+ result.error!
+ end
+ end
+
+ def dao(path, *args, &block)
+ options = args.extract_options!.to_options!
+
+ mode = options[:mode]
+
+ if mode.blank?
+ mode =
+ case request.method
+ when "GET"
+ :read
+ when "PUT", "POST", "DELETE"
+ :write
+ else
+ :read
+ end
+ end
+
+ @dao = api.send(mode, path, params)
+ @dao.route = request.fullpath
+ #@dao.mode = mode
+
+ #unless options[:error!] == false
+ @dao.error! unless @dao.status.ok?
+ #end
+
+ block ? block.call(@dao) : @dao
+ end
end
ApplicationController.send(:include, DaoHelper)
View
6 lib/dao/support.rb
@@ -227,4 +227,10 @@ def tree_walk(node, *path, &block)
end
end
abort 'no suitable uuid generation library detected' unless method_defined?(:uuid)
+
+ def ensure_interface!(object, *interface)
+ interface.flatten.compact.each do |method|
+ raise(NotImplementedError, "#{ object.class.name }##{ method }") unless object.respond_to?(method)
+ end
+ end
end
View
21 lib/dao/upload.rb
@@ -138,7 +138,8 @@ def rewind(io, &block)
end
end
- alias_method :mount, :new
+ alias_method('mount', 'new')
+
attr_accessor :placeholder
end
@@ -176,11 +177,7 @@ def initialize(conducer, *args, &block)
@io = nil
end
- def _update_attributes(attributes = {})
- attributes.to_options!
-
- value = attributes[:value]
-
+ def _set(value)
if value.respond_to?(:read) or value.is_a?(IO)
process_currently_uploaded(value)
else
@@ -188,6 +185,18 @@ def _update_attributes(attributes = {})
end
end
+ def _key
+ key
+ end
+
+ def _value
+ path
+ end
+
+ def _clear
+ clear!
+ end
+
def process_currently_uploaded(value)
Upload.tmpdir do |tmp|
original_basename =
View
17 lib/dao/validations/validator.rb
@@ -172,12 +172,6 @@ def has(key)
alias_method 'has?', 'has'
- def run_validations!(*args)
- run_validations(*args)
- ensure
- validated!
- end
-
def validations_search_path
@validations_search_path ||= (
if mixin?
@@ -221,8 +215,13 @@ def run_validations(list = validations_list)
end
errors
+ ensure
+ validated!(true)
end
+ alias_method 'run_validations!', 'run_validations'
+ alias_method 'validate', 'run_validations'
+
def _run_validations(errors, list)
Array(list).each do |validations|
validations.each do |keys, chain|
@@ -280,10 +279,6 @@ def validated!(boolean = true)
@validated = !!boolean
end
- def validate
- run_validations
- end
-
def validate!
raise Error.new("#{ object.class.name } is invalid!") unless valid?
object
@@ -306,7 +301,7 @@ def valid?(*args)
true
else
options = Map.options_for!(args)
- validate #if(options[:validate] or !validated?)
+ run_validations
errors.empty? and status.ok?
end
end
View
123 test/conducer_test.rb
@@ -2,9 +2,9 @@
Testing Dao::Conducer do
##
#
- context :ctor do
+ context :teh_ctor do
#
- testing 'that conducers have a POLS .new method' do
+ testing 'conducers have a POLS .new method' do
[
{:key => :val, :array => [0,1,2]},
{}
@@ -39,7 +39,7 @@
##
#
- context :default_initialize do
+ context :teh_default_initialize do
#
testing 'that the last mode determines the lifecycle state when a models are passed in' do
user = User.new
@@ -153,7 +153,7 @@ def initialize(a, b, c, params)
##
#
- context :default_save do
+ context :teh_default_save do
#
testing 'is sane and based solely on the last model' do
user = User.new
@@ -170,10 +170,29 @@ def initialize(a, b, c, params)
assert{ comment.text == 'hai!' }
assert{ comment[:user].nil? }
assert{ comment[:post].nil? }
+ end
+
+ #
+ testing 'halts when the conducer is invalid with errors' do
+ conducer_class =
+ new_conducer_class do
+ validates_presence_of(:foo)
+ end
+
+ c = conducer_class.new
+
+ assert{ !c.save }
+ assert{ !c.valid? }
+ assert{ !c.errors.empty? }
+ end
- assert{ comment.errors[:foo] = 'is fucked' }
+ #
+ testing 'halts when the model is invalid and relays errors' do
+ post = Post.new
+ post.errors[:foo] = 'is fucked'
+ c = new_conducer(post)
assert{ !c.save }
- assert{ c.errors[:foo] == Array(comment.errors[:foo]) }
+ assert{ c.errors[:foo] == Array(post.errors[:foo]) }
end
#
@@ -330,6 +349,7 @@ def value() 42 end
assert{ o.errors.respond_to?(:[]) }
end
+=begin
testing 'that conducers can register handlers for setting deeply nested attributes' do
c =
new_conducer_class do
@@ -353,6 +373,70 @@ def _update_attributes(attributes = {})
o = assert{ c.new :name => 'ara howard' }
assert{ o.attributes.get(:name) == 'ara howard' }
end
+=end
+ end
+
+
+ context :teh_mount do
+ testing 'that mounted objects can be declared at the class level' do
+ conducer_class =
+ new_conducer_class do
+ mount Dao::Upload, :a, :b, :placeholder => '/images/foo.jpg'
+ end
+
+ assert{ !conducer_class.mounted.empty? }
+
+ c = conducer_class.new
+
+ assert{ c.mounted.first.is_a?(Dao::Upload) }
+ assert{ c.mounted.first._key.join('.') == 'a.b' }
+ assert{ c.mounted.first._value.nil? }
+ end
+
+ testing 'that mounted objects replace their location in attributes' do
+ conducer_class =
+ new_conducer_class do
+ mount Dao::Upload, :a, :b, :placeholder => '/images/foo.jpg'
+ end
+
+ path = __FILE__
+ up = Upload.new(path)
+
+ c = conducer_class.new( :a => {:b => up} )
+
+ upload = assert{ c.get(:a, :b) }
+
+ assert{ upload.is_a?(Dao::Upload) }
+ assert{ test(?f, upload._value) }
+ end
+
+ testing 'that the default save uses the mounted _value and _clears it' do
+ conducer_class =
+ new_conducer_class do
+ mount Dao::Upload, :up, :placeholder => '/images/foo.jpg'
+ end
+
+ path = File.join(File.dirname(__FILE__), 'data/han-solo.jpg')
+ assert{ test(?s, path) }
+ up = Upload.new(path)
+ comment = Comment.new
+
+ c = conducer_class.new( comment, :up => up )
+
+ upload = assert{ c.get(:up) }
+ assert{ upload.is_a?(Dao::Upload) }
+
+ assert{ test(?f, upload.path) }
+ assert{ File.basename(upload.path) == File.basename(path) }
+ assert{ IO.read(upload.path) == IO.read(path) }
+
+ assert{ c.save }
+
+ value_was_relayed = assert{ comment.attributes[:up] == upload._value }
+ value_was_cleared = assert{ !test(?f, upload.path) }
+
+ assert{ test(?s, path) }
+ end
end
=begin
@@ -412,6 +496,32 @@ def collection
$db[:foos]
end
+ class Mounted
+ def Mounted.mount(*args, &block)
+ new(*args, &block)
+ end
+
+ def _set
+ end
+
+ def _key
+ end
+
+ def _value
+ end
+
+ def _clear
+ end
+ end
+
+ class Upload < StringIO
+ attr_accessor :path
+
+ def initialize(path)
+ super(IO.read(@path = path))
+ end
+ end
+
class Model
{
:new_record => true,
@@ -509,4 +619,5 @@ class Comment < Model
libdir = File.join(rootdir, 'lib')
require File.join(libdir, 'dao')
require File.join(testdir, 'testing')
+ require 'stringio'
}
View
BIN  test/data/han-solo.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

No commit comments for this range

Something went wrong with that request. Please try again.