Renaming Attribute Protection and solving problem modifying the provided hash to the #attributes= method
This commit is contained in:
parent
1d1d815435
commit
d0ed97ed8b
12 changed files with 65 additions and 112 deletions
|
@ -1,68 +0,0 @@
|
|||
module CouchRest
|
||||
module Model
|
||||
module Attributes
|
||||
|
||||
## Support for handling attributes
|
||||
#
|
||||
# This would be better in the properties file, but due to scoping issues
|
||||
# this is not yet possible.
|
||||
#
|
||||
|
||||
def prepare_all_attributes(doc = {}, options = {})
|
||||
apply_all_property_defaults
|
||||
if options[:directly_set_attributes]
|
||||
directly_set_read_only_attributes(doc)
|
||||
else
|
||||
remove_protected_attributes(doc)
|
||||
end
|
||||
directly_set_attributes(doc) unless doc.nil?
|
||||
end
|
||||
|
||||
# Takes a hash as argument, and applies the values by using writer methods
|
||||
# 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)
|
||||
# Remove any protected and update all the rest. Any attributes
|
||||
# which do not have a property will simply be ignored.
|
||||
attrs = remove_protected_attributes(hash)
|
||||
directly_set_attributes(attrs)
|
||||
end
|
||||
alias :attributes= :update_attributes_without_saving
|
||||
|
||||
|
||||
private
|
||||
|
||||
def directly_set_attributes(hash)
|
||||
hash.each do |attribute_name, attribute_value|
|
||||
if self.respond_to?("#{attribute_name}=")
|
||||
self.send("#{attribute_name}=", hash.delete(attribute_name))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def directly_set_read_only_attributes(hash)
|
||||
property_list = self.properties.map{|p| p.name}
|
||||
hash.each do |attribute_name, attribute_value|
|
||||
next if self.respond_to?("#{attribute_name}=")
|
||||
if property_list.include?(attribute_name)
|
||||
write_attribute(attribute_name, hash.delete(attribute_name))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def set_attributes(hash)
|
||||
attrs = remove_protected_attributes(hash)
|
||||
directly_set_attributes(attrs)
|
||||
end
|
||||
|
||||
def check_properties_exist(attrs)
|
||||
property_list = self.properties.map{|p| p.name}
|
||||
attrs.each do |attribute_name, attribute_value|
|
||||
raise NoMethodError, "Property #{attribute_name} not created" unless respond_to?("#{attribute_name}=") or property_list.include?(attribute_name)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -13,7 +13,7 @@ module CouchRest
|
|||
include CouchRest::Model::ExtendedAttachments
|
||||
include CouchRest::Model::ClassProxy
|
||||
include CouchRest::Model::Collection
|
||||
include CouchRest::Model::AttributeProtection
|
||||
include CouchRest::Model::PropertyProtection
|
||||
include CouchRest::Model::Associations
|
||||
include CouchRest::Model::Validations
|
||||
|
||||
|
@ -47,7 +47,7 @@ module CouchRest
|
|||
# * :directly_set_attributes: true when data comes directly from database
|
||||
#
|
||||
def initialize(doc = {}, options = {})
|
||||
prepare_all_attributes(doc, options)
|
||||
doc = prepare_all_attributes(doc, options)
|
||||
super(doc)
|
||||
unless self['_id'] && self['_rev']
|
||||
self[self.model_type_key] = self.class.to_s
|
||||
|
|
|
@ -7,7 +7,7 @@ module CouchRest::Model
|
|||
include CouchRest::Model::Configuration
|
||||
include CouchRest::Model::Callbacks
|
||||
include CouchRest::Model::Properties
|
||||
include CouchRest::Model::AttributeProtection
|
||||
include CouchRest::Model::PropertyProtection
|
||||
include CouchRest::Model::Associations
|
||||
include CouchRest::Model::Validations
|
||||
attr_accessor :casted_by
|
||||
|
|
|
@ -12,7 +12,7 @@ module CouchRest
|
|||
add_config :mass_assign_any_attribute
|
||||
|
||||
configure do |config|
|
||||
config.model_type_key = 'model'
|
||||
config.model_type_key = 'couchrest-type' # 'model'?
|
||||
config.mass_assign_any_attribute = false
|
||||
end
|
||||
end
|
||||
|
|
|
@ -61,7 +61,7 @@ module CouchRest
|
|||
if options[:directly_set_attributes]
|
||||
directly_set_read_only_attributes(doc)
|
||||
else
|
||||
remove_protected_attributes(doc)
|
||||
doc = remove_protected_attributes(doc)
|
||||
end
|
||||
directly_set_attributes(doc) unless doc.nil?
|
||||
end
|
||||
|
@ -72,12 +72,18 @@ module CouchRest
|
|||
prop
|
||||
end
|
||||
|
||||
# Set all the attributes and return a hash with the attributes
|
||||
# that have not been accepted.
|
||||
def directly_set_attributes(hash)
|
||||
hash.each do |attribute_name, attribute_value|
|
||||
hash.reject do |attribute_name, attribute_value|
|
||||
if self.respond_to?("#{attribute_name}=")
|
||||
self.send("#{attribute_name}=", hash.delete(attribute_name))
|
||||
self.send("#{attribute_name}=", attribute_value)
|
||||
true
|
||||
elsif mass_assign_any_attribute # config option
|
||||
self[attribute_name] = attribute_value
|
||||
true
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
module CouchRest
|
||||
module Model
|
||||
module AttributeProtection
|
||||
module PropertyProtection
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
# Attribute protection from mass assignment to CouchRest::Model properties
|
||||
# Property protection from mass assignment to CouchRest::Model properties
|
||||
#
|
||||
# Protected methods will be removed from
|
||||
# * new
|
||||
|
@ -22,7 +22,7 @@ module CouchRest
|
|||
#
|
||||
# 3) Mix and match, and assume all unspecified properties are protected.
|
||||
# property :name, :accessible => true
|
||||
# property :admin, :protected => true
|
||||
# property :admin, :protected => true # ignored
|
||||
# property :phone # this will be automatically protected
|
||||
#
|
||||
# Note: the timestamps! method protectes the created_at and updated_at properties
|
||||
|
@ -34,11 +34,16 @@ module CouchRest
|
|||
|
||||
module ClassMethods
|
||||
def accessible_properties
|
||||
properties.select { |prop| prop.options[:accessible] }
|
||||
props = properties.select { |prop| prop.options[:accessible] }
|
||||
if props.empty?
|
||||
props = properties.select { |prop| !prop.options[:protected] }
|
||||
end
|
||||
props
|
||||
end
|
||||
|
||||
def protected_properties
|
||||
properties.select { |prop| prop.options[:protected] }
|
||||
accessibles = accessible_properties
|
||||
properties.reject { |prop| accessibles.include?(prop) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -50,28 +55,17 @@ module CouchRest
|
|||
self.class.protected_properties
|
||||
end
|
||||
|
||||
# Return a new copy of the attributes hash with protected attributes
|
||||
# removed.
|
||||
def remove_protected_attributes(attributes)
|
||||
protected_names = properties_to_remove_from_mass_assignment.map { |prop| prop.name }
|
||||
return attributes if protected_names.empty?
|
||||
protected_names = protected_properties.map { |prop| prop.name }
|
||||
return attributes if protected_names.empty? or attributes.nil?
|
||||
|
||||
attributes.reject! do |property_name, property_value|
|
||||
attributes.reject do |property_name, property_value|
|
||||
protected_names.include?(property_name.to_s)
|
||||
end if attributes
|
||||
|
||||
attributes || {}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def properties_to_remove_from_mass_assignment
|
||||
to_remove = protected_properties
|
||||
|
||||
unless accessible_properties.empty?
|
||||
to_remove += properties.reject { |prop| prop.options[:accessible] }
|
||||
end
|
||||
|
||||
to_remove
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue