aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorDavid Dollar <ddollar@gmail.com>2008-07-13 21:13:50 -0400
committerPratik Naik <pratiknaik@gmail.com>2008-07-14 02:53:21 +0100
commite0750d6a5c7f621e4ca12205137c0b135cab444a (patch)
tree442e795385f4114b8270e9d5d325b307bbb1bc13 /activerecord/lib
parentc6f397c5cecf183680c191dd2128c0a96c5b9399 (diff)
downloadrails-e0750d6a5c7f621e4ca12205137c0b135cab444a.tar.gz
rails-e0750d6a5c7f621e4ca12205137c0b135cab444a.tar.bz2
rails-e0750d6a5c7f621e4ca12205137c0b135cab444a.zip
Add :accessible option to Associations for allowing mass assignments using hash. [#474 state:resolved]
Allows nested Hashes (i.e. from nested forms) to hydrate the appropriate ActiveRecord models. class Post < ActiveRecord::Base belongs_to :author, :accessible => true has_many :comments, :accessible => true end post = Post.create({ :title => 'Accessible Attributes', :author => { :name => 'David Dollar' }, :comments => [ { :body => 'First Post!' }, { :body => 'Nested Hashes are great!' } ] }) post.comments << { :body => 'Another Comment' } Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
Diffstat (limited to 'activerecord/lib')
-rwxr-xr-xactiverecord/lib/active_record/associations.rb14
-rw-r--r--activerecord/lib/active_record/associations/association_collection.rb6
2 files changed, 16 insertions, 4 deletions
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 6931744058..d43e07ab4e 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -692,6 +692,7 @@ module ActiveRecord
# * <tt>:uniq</tt> - If true, duplicates will be omitted from the collection. Useful in conjunction with <tt>:through</tt>.
# * <tt>:readonly</tt> - If true, all the associated objects are readonly through the association.
# * <tt>:validate</tt> - If false, don't validate the associated objects when saving the parent object. true by default.
+ # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
#
# Option examples:
# has_many :comments, :order => "posted_on"
@@ -774,6 +775,7 @@ module ActiveRecord
# association is a polymorphic +belongs_to+.
# * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
# * <tt>:validate</tt> - If false, don't validate the associated object when saving the parent object. +false+ by default.
+ # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
#
# Option examples:
# has_one :credit_card, :dependent => :destroy # destroys the associated credit card
@@ -863,6 +865,7 @@ module ActiveRecord
# to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
# * <tt>:readonly</tt> - If true, the associated object is readonly through the association.
# * <tt>:validate</tt> - If false, don't validate the associated objects when saving the parent object. +false+ by default.
+ # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
#
# Option examples:
# belongs_to :firm, :foreign_key => "client_of"
@@ -1034,6 +1037,7 @@ module ActiveRecord
# but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error.
# * <tt>:readonly</tt> - If true, all the associated objects are readonly through the association.
# * <tt>:validate</tt> - If false, don't validate the associated objects when saving the parent object. +true+ by default.
+ # * <tt>:accessible</tt> - Mass assignment is allowed for this assocation (similar to <tt>ActiveRecord::Base#attr_accessible</tt>).
#
# Option examples:
# has_and_belongs_to_many :projects
@@ -1109,6 +1113,8 @@ module ActiveRecord
association = association_proxy_class.new(self, reflection)
end
+ new_value = reflection.klass.new(new_value) if reflection.options[:accessible] && new_value.is_a?(Hash)
+
if association_proxy_class == HasOneThroughAssociation
association.create_through_record(new_value)
self.send(reflection.name, new_value)
@@ -1357,7 +1363,7 @@ module ActiveRecord
:finder_sql, :counter_sql,
:before_add, :after_add, :before_remove, :after_remove,
:extend, :readonly,
- :validate
+ :validate, :accessible
)
options[:extend] = create_extension_modules(association_id, extension, options[:extend])
@@ -1367,7 +1373,7 @@ module ActiveRecord
def create_has_one_reflection(association_id, options)
options.assert_valid_keys(
- :class_name, :foreign_key, :remote, :select, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :readonly, :validate, :primary_key
+ :class_name, :foreign_key, :remote, :select, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :readonly, :validate, :primary_key, :accessible
)
create_reflection(:has_one, association_id, options, self)
@@ -1383,7 +1389,7 @@ module ActiveRecord
def create_belongs_to_reflection(association_id, options)
options.assert_valid_keys(
:class_name, :foreign_key, :foreign_type, :remote, :select, :conditions, :include, :dependent,
- :counter_cache, :extend, :polymorphic, :readonly, :validate
+ :counter_cache, :extend, :polymorphic, :readonly, :validate, :accessible
)
reflection = create_reflection(:belongs_to, association_id, options, self)
@@ -1403,7 +1409,7 @@ module ActiveRecord
:finder_sql, :delete_sql, :insert_sql,
:before_add, :after_add, :before_remove, :after_remove,
:extend, :readonly,
- :validate
+ :validate, :accessible
)
options[:extend] = create_extension_modules(association_id, extension, options[:extend])
diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb
index 04be59e89d..a28be9eed1 100644
--- a/activerecord/lib/active_record/associations/association_collection.rb
+++ b/activerecord/lib/active_record/associations/association_collection.rb
@@ -97,6 +97,8 @@ module ActiveRecord
@owner.transaction do
flatten_deeper(records).each do |record|
+ record = @reflection.klass.new(record) if @reflection.options[:accessible] && record.is_a?(Hash)
+
raise_on_type_mismatch(record)
add_record_to_target_with_callbacks(record) do |r|
result &&= insert_record(record) unless @owner.new_record?
@@ -229,6 +231,10 @@ module ActiveRecord
# Replace this collection with +other_array+
# This will perform a diff and delete/add only records that have changed.
def replace(other_array)
+ other_array.map! do |val|
+ val.is_a?(Hash) ? @reflection.klass.new(val) : val
+ end if @reflection.options[:accessible]
+
other_array.each { |val| raise_on_type_mismatch(val) }
load_target