Fixing and testing proxyable with associations and validation
This commit is contained in:
parent
8fa7e87019
commit
760d855845
10 changed files with 135 additions and 102 deletions
|
@ -36,15 +36,12 @@ module CouchRest
|
|||
# it can be set with the :proxy_name option.
|
||||
#
|
||||
def belongs_to(attrib, *options)
|
||||
opts = merge_belongs_to_association_options(attrib, options.first)
|
||||
|
||||
opts = merge_belongs_to_assocation_options(attrib, options.first)
|
||||
property(opts[:foreign_key], opts)
|
||||
|
||||
prop = property(opts[:foreign_key], opts)
|
||||
|
||||
create_belongs_to_getter(attrib, prop, opts)
|
||||
create_belongs_to_setter(attrib, prop, opts)
|
||||
|
||||
prop
|
||||
create_belongs_to_getter(attrib, opts)
|
||||
create_belongs_to_setter(attrib, opts)
|
||||
end
|
||||
|
||||
# Provide access to a collection of objects where the associated
|
||||
|
@ -87,41 +84,27 @@ module CouchRest
|
|||
# frequently! Use with prudence.
|
||||
#
|
||||
def collection_of(attrib, *options)
|
||||
|
||||
opts = merge_belongs_to_assocation_options(attrib, options.first)
|
||||
opts = merge_belongs_to_association_options(attrib, options.first)
|
||||
opts[:foreign_key] = opts[:foreign_key].pluralize
|
||||
opts[:readonly] = true
|
||||
|
||||
prop = property(opts[:foreign_key], [], opts)
|
||||
property(opts[:foreign_key], [], opts)
|
||||
|
||||
create_collection_of_property_setter(attrib, prop, opts)
|
||||
create_collection_of_getter(attrib, prop, opts)
|
||||
create_collection_of_setter(attrib, prop, opts)
|
||||
|
||||
prop
|
||||
create_collection_of_property_setter(attrib, opts)
|
||||
create_collection_of_getter(attrib, opts)
|
||||
create_collection_of_setter(attrib, opts)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def merge_belongs_to_assocation_options(attrib, options = nil)
|
||||
def merge_belongs_to_association_options(attrib, options = nil)
|
||||
opts = {
|
||||
:foreign_key => attrib.to_s + '_id',
|
||||
:class_name => attrib.to_s.camelcase,
|
||||
:foreign_key => attrib.to_s.singularize + '_id',
|
||||
:class_name => attrib.to_s.singularize.camelcase,
|
||||
:proxy_name => attrib.to_s.pluralize
|
||||
}
|
||||
|
||||
# merge the options
|
||||
case options
|
||||
when Hash
|
||||
opts.merge!(options)
|
||||
end
|
||||
# Get a class name
|
||||
begin
|
||||
opts[:class] = opts[:class_name].constantize
|
||||
rescue NameError
|
||||
raise NameError, "Unable to convert class name into Constant for #{self.name}##{attrib}"
|
||||
end
|
||||
opts.merge!(options) if options.is_a?(Hash)
|
||||
|
||||
# Generate a string for the proxy method call
|
||||
# Assumes that the proxy_owner_method from "proxyable" is available.
|
||||
|
@ -129,14 +112,14 @@ module CouchRest
|
|||
opts[:proxy] = if proxy_owner_method
|
||||
"self.#{proxy_owner_method}.#{opts[:proxy_name]}"
|
||||
else
|
||||
opts[:class_name].constantize
|
||||
opts[:class_name]
|
||||
end
|
||||
end
|
||||
|
||||
opts
|
||||
end
|
||||
|
||||
def create_belongs_to_getter(attrib, property, options)
|
||||
def create_belongs_to_getter(attrib, options)
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
def #{attrib}
|
||||
@#{attrib} ||= #{options[:foreign_key]}.nil? ? nil : #{options[:proxy]}.get(self.#{options[:foreign_key]})
|
||||
|
@ -144,7 +127,7 @@ module CouchRest
|
|||
EOS
|
||||
end
|
||||
|
||||
def create_belongs_to_setter(attrib, property, options)
|
||||
def create_belongs_to_setter(attrib, options)
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
def #{attrib}=(value)
|
||||
self.#{options[:foreign_key]} = value.nil? ? nil : value.id
|
||||
|
@ -155,7 +138,7 @@ module CouchRest
|
|||
|
||||
### collection_of support methods
|
||||
|
||||
def create_collection_of_property_setter(attrib, property, options)
|
||||
def create_collection_of_property_setter(attrib, options)
|
||||
# ensure CollectionOfProxy is nil, ready to be reloaded on request
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
def #{options[:foreign_key]}=(value)
|
||||
|
@ -165,18 +148,17 @@ module CouchRest
|
|||
EOS
|
||||
end
|
||||
|
||||
def create_collection_of_getter(attrib, property, options)
|
||||
base = options[:proxy] || options[:class_name]
|
||||
def create_collection_of_getter(attrib, options)
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
def #{attrib}(reload = false)
|
||||
return @#{attrib} unless @#{attrib}.nil? or reload
|
||||
ary = self.#{options[:foreign_key]}.collect{|i| #{base}.get(i)}
|
||||
ary = self.#{options[:foreign_key]}.collect{|i| #{options[:proxy]}.get(i)}
|
||||
@#{attrib} = ::CouchRest::CollectionOfProxy.new(ary, self, '#{options[:foreign_key]}')
|
||||
end
|
||||
EOS
|
||||
end
|
||||
|
||||
def create_collection_of_setter(attrib, property, options)
|
||||
def create_collection_of_setter(attrib, options)
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
def #{attrib}=(value)
|
||||
@#{attrib} = ::CouchRest::CollectionOfProxy.new(value, self, '#{options[:foreign_key]}')
|
||||
|
|
|
@ -6,14 +6,11 @@ module CouchRest
|
|||
|
||||
module ClassMethods
|
||||
|
||||
attr_reader :proxy_owner_method
|
||||
|
||||
# Define a collection that will use the base model for the database connection
|
||||
# details.
|
||||
def proxy_for(assoc_name, options = {})
|
||||
db_method = options[:database_method] || "proxy_database"
|
||||
options[:class_name] ||= assoc_name.to_s.singularize.camelize
|
||||
attr_accessor :model_proxy
|
||||
class_eval <<-EOS, __FILE__, __LINE__ + 1
|
||||
def #{assoc_name}
|
||||
unless respond_to?('#{db_method}')
|
||||
|
@ -27,8 +24,16 @@ module CouchRest
|
|||
def proxied_by(model_name, options = {})
|
||||
raise "Model can only be proxied once or ##{model_name} already defined" if method_defined?(model_name) || !proxy_owner_method.nil?
|
||||
self.proxy_owner_method = model_name
|
||||
attr_accessor :model_proxy
|
||||
attr_accessor model_name
|
||||
end
|
||||
|
||||
# Define an a class variable accessor ready to be inherited and unique
|
||||
# for each Class using the base.
|
||||
# Perhaps there is a shorter way of writing this.
|
||||
def proxy_owner_method=(name); @proxy_owner_method = name; end
|
||||
def proxy_owner_method; @proxy_owner_method; end
|
||||
|
||||
end
|
||||
|
||||
class ModelProxy
|
||||
|
@ -132,10 +137,10 @@ module CouchRest
|
|||
# Update the document's proxy details, specifically, the fields that
|
||||
# link back to the original document.
|
||||
def proxy_update(doc)
|
||||
if doc
|
||||
doc.database = @database if doc.respond_to?(:database=)
|
||||
doc.model_proxy = self if doc.respond_to?(:model_proxy=)
|
||||
doc.send("#{owner_name}=", owner) if doc.respond_to?("#{owner_name}=")
|
||||
if doc && doc.is_a?(model)
|
||||
doc.database = @database
|
||||
doc.model_proxy = self
|
||||
doc.send("#{owner_name}=", owner)
|
||||
end
|
||||
doc
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ module CouchRest
|
|||
def validate_each(document, attribute, value)
|
||||
view_name = options[:view].nil? ? "by_#{attribute}" : options[:view]
|
||||
|
||||
model = (respond_to?(:model_proxy) && model_proxy ? model_proxy : @model)
|
||||
model = (document.respond_to?(:model_proxy) && document.model_proxy ? document.model_proxy : @model)
|
||||
# Determine the base of the search
|
||||
base = options[:proxy].nil? ? model : document.instance_eval(options[:proxy])
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ module CouchRest
|
|||
query = query.dup # Modifications made on copy!
|
||||
db = query.delete(:database) || database
|
||||
refresh_design_doc(db)
|
||||
query[:raw] = true if query[:reduce]
|
||||
query[:raw] = true if query[:reduce]
|
||||
raw = query.delete(:raw)
|
||||
fetch_view_with_docs(db, name, query, raw, &block)
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue