Using accepts_nested_attributes_for When the Child Object validates_presence_of Parent
- 0 comments
- tagged with rails, bug, code, ruby
I came across an interesting dilemma today in Rails 2.3 whilst trying to use accepts_nested_attributes_for.
The models I have were:
class Organization < ActiveRecord::Basehas_many :usersaccepts_nested_attributes_for :usersendclass User < ActiveRecord::Basebelongs_to :organizationvalidates_presence_of :organizationend
I had an “Organization” creation form which allowed an administrator to create an Organization and an initial user for it. However, even though I had filled in all the required fields to pass the validations I was constantly getting the following error: Organization can not be blank.
Digging deeper I found that when an object is added to an association via the association.build method, the parent object isn’t actually set:
>> o = Organization.new(:name => "Test")=> #<Organization id: nil, name: "Test">>> u = o.users.build(:name => "Test User")=> #<User id: nil, organization_id: nil, name: "Test User">>> u.organization=> nil
Apparently this flaw also applies to accepts_nested_attributes_for. When I send through the User params through from my form normally with the Organization params, it creates the User object in the users association as you’d expect, but raises a validation error because the User instance doesn’t recognise that it is has a parent Organization
My quick 5 minute fix was to modify the Organization model thusly:
class Organization < ActiveRecord::Basehas_many :usersaccepts_nested_attributes_for :usersdef users_attributes_with_self_assignment=(attributes)self.users_attributes_without_self_assignment = attributesusers.each { |u| u.organization = self }endalias_method_chain :users_attributes=, :self_assignmentend
Related Rails bugs seem to be here and here. This patch will also solve the problem and is currently in edge, but didn’t make it in time for Rails 2.3.