Merge commit 'sethladd/master'
This commit is contained in:
commit
cdf998b185
7 changed files with 123 additions and 91 deletions
|
@ -37,37 +37,55 @@ module CouchRest
|
|||
def cast_keys
|
||||
return unless self.class.properties
|
||||
self.class.properties.each do |property|
|
||||
next unless property.casted
|
||||
key = self.has_key?(property.name) ? property.name : property.name.to_sym
|
||||
# Don't cast the property unless it has a value
|
||||
next unless self[key]
|
||||
target = property.type
|
||||
if target.is_a?(Array)
|
||||
klass = ::CouchRest.constantize(target[0])
|
||||
arr = self[key].collect do |value|
|
||||
# Auto parse Time objects
|
||||
obj = ( (property.init_method == 'new') && klass == Time) ? Time.parse(value) : klass.send(property.init_method, value)
|
||||
obj.casted_by = self if obj.respond_to?(:casted_by)
|
||||
obj.document_saved = true if obj.respond_to?(:document_saved)
|
||||
obj
|
||||
end
|
||||
self[property.name] = target[0] != 'String' ? CastedArray.new(arr) : arr
|
||||
else
|
||||
# Auto parse Time objects
|
||||
self[property.name] = if ((property.init_method == 'new') && target == 'Time')
|
||||
self[key].is_a?(String) ? Time.parse(self[key].dup) : self[key]
|
||||
else
|
||||
# Let people use :send as a Time parse arg
|
||||
klass = ::CouchRest.constantize(target)
|
||||
klass.send(property.init_method, self[key].dup)
|
||||
end
|
||||
self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by)
|
||||
self[property.name].document_saved = true if self[property.name].respond_to?(:document_saved)
|
||||
end
|
||||
self[property.name].casted_by = self if self[property.name].respond_to?(:casted_by)
|
||||
cast_property(property)
|
||||
end
|
||||
end
|
||||
|
||||
def cast_property(property)
|
||||
return unless property.casted
|
||||
key = self.has_key?(property.name) ? property.name : property.name.to_sym
|
||||
# Don't cast the property unless it has a value
|
||||
return unless self[key]
|
||||
target = property.type
|
||||
if target.is_a?(Array)
|
||||
klass = ::CouchRest.constantize(target[0])
|
||||
arr = self[key].dup.collect do |value|
|
||||
unless value.instance_of?(klass)
|
||||
value = convert_property_value(property, klass, value)
|
||||
end
|
||||
associate_casted_to_parent(value)
|
||||
value
|
||||
end
|
||||
self[key] = target[0] != 'String' ? CastedArray.new(arr) : arr
|
||||
else
|
||||
klass = ::CouchRest.constantize(target)
|
||||
unless self[key].instance_of?(klass)
|
||||
self[key] = convert_property_value(property, klass, self[property.name])
|
||||
end
|
||||
associate_casted_to_parent(self[property.name])
|
||||
end
|
||||
end
|
||||
|
||||
def associate_casted_to_parent(casted)
|
||||
casted.casted_by = self if casted.respond_to?(:casted_by)
|
||||
casted.document_saved = true if casted.respond_to?(:document_saved)
|
||||
end
|
||||
|
||||
def convert_property_value(property, klass, value)
|
||||
if ((property.init_method == 'new') && klass.to_s == 'Time')
|
||||
value.is_a?(String) ? Time.parse(value.dup) : value
|
||||
else
|
||||
klass.send(property.init_method, value.dup)
|
||||
end
|
||||
end
|
||||
|
||||
def cast_property_by_name(property_name)
|
||||
return unless self.class.properties
|
||||
property = self.class.properties.detect{|property| property.name == property_name}
|
||||
return unless property
|
||||
cast_property(property)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
|
||||
def property(name, options={})
|
||||
|
@ -108,24 +126,17 @@ module CouchRest
|
|||
|
||||
# defines the setter for the property (and optional aliases)
|
||||
def create_property_setter(property)
|
||||
meth = property.name
|
||||
property_name = property.name
|
||||
class_eval <<-EOS
|
||||
def #{meth}=(value)
|
||||
if #{property.casted} && value.is_a?(Array)
|
||||
arr = CastedArray.new
|
||||
arr.casted_by = self
|
||||
value.each { |v| arr << v }
|
||||
value = arr
|
||||
elsif #{property.casted}
|
||||
value.casted_by = self if value.respond_to?(:casted_by)
|
||||
end
|
||||
self['#{meth}'] = value
|
||||
def #{property_name}=(value)
|
||||
self['#{property_name}'] = value
|
||||
cast_property_by_name('#{property_name}')
|
||||
end
|
||||
EOS
|
||||
|
||||
if property.alias
|
||||
class_eval <<-EOS
|
||||
alias #{property.alias.to_sym}= #{meth.to_sym}=
|
||||
alias #{property.alias.to_sym}= #{property_name.to_sym}=
|
||||
EOS
|
||||
end
|
||||
end
|
||||
|
|
|
@ -51,9 +51,6 @@ module CouchRest
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
# Automatically set <tt>updated_at</tt> and <tt>created_at</tt> fields
|
||||
# on the document whenever saving occurs. CouchRest uses a pretty
|
||||
# decent time format by default. See Time#to_json
|
||||
|
@ -68,7 +65,7 @@ module CouchRest
|
|||
end
|
||||
EOS
|
||||
end
|
||||
|
||||
|
||||
# Name a method that will be called before the document is first saved,
|
||||
# which returns a string to be used for the document's <tt>_id</tt>.
|
||||
# Because CouchDB enforces a constraint that each id must be unique,
|
||||
|
@ -127,10 +124,15 @@ module CouchRest
|
|||
# for each key. It doesn't save the document at the end. Raises a NoMethodError if the corresponding methods are
|
||||
# missing. In case of error, no attributes are changed.
|
||||
def update_attributes_without_saving(hash)
|
||||
hash.each do |k, v|
|
||||
# remove attributes that cannot be updated, silently ignoring them
|
||||
# which matches Rails behavior when, for instance, setting created_at.
|
||||
# make a copy, we don't want to change arguments
|
||||
attrs = hash.dup
|
||||
%w[_id _rev created_at updated_at].each {|attr| attrs.delete(attr)}
|
||||
attrs.each do |k, v|
|
||||
raise NoMethodError, "#{k}= method not available, use property :#{k}" unless self.respond_to?("#{k}=")
|
||||
end
|
||||
hash.each do |k, v|
|
||||
attrs.each do |k, v|
|
||||
self.send("#{k}=",v)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,52 +1,53 @@
|
|||
# This file contains various hacks for Rails compatibility.
|
||||
# To use, just require in environment.rb, like so:
|
||||
#
|
||||
# require 'couchrest/support/rails'
|
||||
|
||||
class Hash
|
||||
# Hack so that CouchRest::Document, which descends from Hash,
|
||||
# doesn't appear to Rails routing as a Hash of options
|
||||
def self.===(other)
|
||||
return false if self == Hash && other.is_a?(CouchRest::Document)
|
||||
super
|
||||
if defined?(Rails)
|
||||
|
||||
class Hash
|
||||
# Hack so that CouchRest::Document, which descends from Hash,
|
||||
# doesn't appear to Rails routing as a Hash of options
|
||||
def self.===(other)
|
||||
return false if self == Hash && other.is_a?(CouchRest::Document)
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
CouchRest::Document.class_eval do
|
||||
# Need this when passing doc to a resourceful route
|
||||
alias_method :to_param, :id
|
||||
CouchRest::Document.class_eval do
|
||||
# Need this when passing doc to a resourceful route
|
||||
alias_method :to_param, :id
|
||||
|
||||
# Hack so that CouchRest::Document, which descends from Hash,
|
||||
# doesn't appear to Rails routing as a Hash of options
|
||||
def is_a?(o)
|
||||
return false if o == Hash
|
||||
super
|
||||
end
|
||||
alias_method :kind_of?, :is_a?
|
||||
# Hack so that CouchRest::Document, which descends from Hash,
|
||||
# doesn't appear to Rails routing as a Hash of options
|
||||
def is_a?(o)
|
||||
return false if o == Hash
|
||||
super
|
||||
end
|
||||
alias_method :kind_of?, :is_a?
|
||||
|
||||
# Gives extended doc a seamless logger
|
||||
def logger
|
||||
ActiveRecord::Base.logger
|
||||
# Gives extended doc a seamless logger
|
||||
def logger
|
||||
ActiveRecord::Base.logger
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
CouchRest::CastedModel.class_eval do
|
||||
# The to_param method is needed for rails to generate resourceful routes.
|
||||
# In your controller, remember that it's actually the id of the document.
|
||||
def id
|
||||
return nil if base_doc.nil?
|
||||
base_doc.id
|
||||
CouchRest::CastedModel.class_eval do
|
||||
# The to_param method is needed for rails to generate resourceful routes.
|
||||
# In your controller, remember that it's actually the id of the document.
|
||||
def id
|
||||
return nil if base_doc.nil?
|
||||
base_doc.id
|
||||
end
|
||||
alias_method :to_param, :id
|
||||
end
|
||||
alias_method :to_param, :id
|
||||
end
|
||||
|
||||
require Pathname.new(File.dirname(__FILE__)).join('..', 'validation', 'validation_errors')
|
||||
require Pathname.new(File.dirname(__FILE__)).join('..', 'validation', 'validation_errors')
|
||||
|
||||
CouchRest::Validation::ValidationErrors.class_eval do
|
||||
# Returns the total number of errors added. Two errors added to the same attribute will be counted as such.
|
||||
# This method is called by error_messages_for
|
||||
def count
|
||||
errors.values.inject(0) { |error_count, errors_for_attribute| error_count + errors_for_attribute.size }
|
||||
CouchRest::Validation::ValidationErrors.class_eval do
|
||||
# Returns the total number of errors added. Two errors added to the same attribute will be counted as such.
|
||||
# This method is called by error_messages_for
|
||||
def count
|
||||
errors.values.inject(0) { |error_count, errors_for_attribute| error_count + errors_for_attribute.size }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue