Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Nested attribute setters can be overridden. #2945

Merged
merged 1 commit into from

7 participants

@Peeja

We needed to use some of the features of accepts_nested_attributes_for (such as :_destroy) but we needed to filter the incoming attributes. This patch puts the methods accepts_nested_attributes_for defines in a module which can sit behind a custom implementation so that it can call super.

@josevalim
Owner

I like this. However, instead of creating a new module, can't we simply use the original attributes module?

@Peeja

I don't think that's wise. ActiveModel::AttributeMethods owns that module, and this is independent of that system. For instance, calling attribute_method_prefix (or the other similar declarations) undefines all of the methods in that module. It would blow these away too, and not know to redefine them.

@josevalim
Owner

Good point. /cc @jonleighton @tenderlove

@jonleighton
Collaborator

we should use the generated_feature_methods module

@carlosantoniodasilva

@Peeja any possibility of changing the pull request to use the generated_feature_methods module as per @jonleighton suggestion? Thanks.

@Peeja

Yep, it's been sitting on my list for...boy, 2 months? Yeah, I'll get on it.

Jonathan Mukai & Peter Jaros Nested attribute setters can be overridden.
Overriding implementation can call super.
135d704
@Peeja

Updated, but I'm having trouble getting the pull request to register the change. Please stand by.

@Peeja

Commenting seems to have done it. :)

Question: Now NestedAttributes depends on Core (for generated_feature_methods). Is that kosher? Or does that dependency need to be explicit somehow (like includeing Core, which doesn't seem right either).

@carlosantoniodasilva

I think we can just think that Core should always be there. @jonleighton any thought? Thanks.

@jonleighton
Collaborator

Yeah that's fine. At the moment, the use of modules in AR is mainly for code organisation really - there are lots of dependencies between different modules. I'll merge this, thanks!

@jonleighton jonleighton merged commit 3a8c543 into from
@davisre

Is there any chance of getting this into 3.2? There's a workaround, but calling super would be much nicer than calling assign_nested_attributes_for_collection_association. And we already have it for associations and normal attributes.

@TylerRick

+1 for backporting to 3.2...

In the meantime, you can always do what I did and just copy and paste the fix into your project. Yay.

@rafaelfranca

I don't think we should backport this since it is more a new feature that a bug fix

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 28, 2012
  1. @Peeja

    Nested attribute setters can be overridden.

    Jonathan Mukai & Peter Jaros authored Peeja committed
    Overriding implementation can call super.
This page is out of date. Refresh to see the latest.
View
2  activerecord/lib/active_record/nested_attributes.rb
@@ -288,7 +288,7 @@ def accepts_nested_attributes_for(*attr_names)
# def pirate_attributes=(attributes)
# assign_nested_attributes_for_one_to_one_association(:pirate, attributes, mass_assignment_options)
# end
- class_eval <<-eoruby, __FILE__, __LINE__ + 1
+ generated_feature_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
if method_defined?(:#{association_name}_attributes=)
remove_method(:#{association_name}_attributes=)
end
View
13 activerecord/test/cases/nested_attributes_test.rb
@@ -172,6 +172,19 @@ def test_first_and_array_index_zero_methods_return_the_same_value_when_nested_at
man.interests_attributes = [{:id => interest.id, :topic => 'gardening'}]
assert_equal man.interests.first.topic, man.interests[0].topic
end
+
+ def test_allows_class_to_override_setter_and_call_super
+ mean_pirate_class = Class.new(Pirate) do
+ accepts_nested_attributes_for :parrot
+ def parrot_attributes=(attrs)
+ super(attrs.merge(:color => "blue"))
+ end
+ end
+ mean_pirate = mean_pirate_class.new
+ mean_pirate.parrot_attributes = { :name => "James" }
+ assert_equal "James", mean_pirate.parrot.name
+ assert_equal "blue", mean_pirate.parrot.color
+ end
end
class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
View
1  activerecord/test/schema/schema.rb
@@ -439,6 +439,7 @@ def create_table(*args, &block)
create_table :parrots, :force => true do |t|
t.column :name, :string
+ t.column :color, :string
t.column :parrot_sti_class, :string
t.column :killer_id, :integer
t.column :created_at, :datetime
Something went wrong with that request. Please try again.