acts_as_nested_by
“acts_as_nested_by” is/will be a simple counterpart for rails’ “accepts_attribute_for”.
Use case example
Since the rails-way of handling referential integrity is to code the logic into you your model, without using database dependent foreign key constraints, you might come across situations like this.
class Foo < ActiveRecord
has_many :bars
validates_associated :bars
accepts_nested_attributes_for :bars
end
class Bar < ActiveRecord
belongs_to :foo
validates_presence_of :foo
end
Using validates_presence_of :foo instead of :foo_id ensures that not only a :foo_id was given but a Foo object existst in the :foos table.
But on creation of a Foo with nested Bars in on step produces a kind of dead look, since the :foo_id for the Bars is not available until the Foo ist saved, and the validates_presence_of :bars produces an error in the Bars, no :foo_id, no Foo in the :foos table. And because the Foo :validates_associated :bars it cannot be saved. Using an :unless => :new_record? conditions with the validations might help, but it can but those valdation would also be skipped, if the Bars were not to be created in a nested form.
To handle this acts_as_nested_by comes in handy.
class Bar < ActiveRecord
belongs_to :foo
acts_as_nested_by :foo
validates_presence_of :foo, :unless => :nested_by_foo?
end
Now just pass a parameter (with a hidden form parameter, or in the controller) :nested_by_foo => true when creating Bars nested in a Foo. If the Foo ist valid? it can be saved and the nested Bars will be auto saved and consistency is assured. ;)
Nota bene
When using :attr_accessible, :attr_proteced and a hidden form parameter you should add :nested_by_foo to the mass-assignable attributes.
Next steps/known issues
Since the setting of :nested_by_foo via mass assignement could be exploited to create inconsitent entries, the build/create methods provide by the association macros should set the :nested_by_foo internaly and the generated ActiveRecord::Base#nested_by_foo should be defined protected.
Note on Patches/Pull Requests
-
Fork the project.
-
Make your feature addition or bug fix.
-
Add tests for it. This is important so I don’t break it in a future version unintentionally.
-
Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
-
Send me a pull request. Bonus points for topic branches.
Copyright
Copyright © 2010 Thomas Limp. See LICENSE for details.