Using accepts_nested_attributes_for When the Child Object validates_presence_of Parent
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::Base
has_many :users
accepts_nested_attributes_for :users
end
class User < ActiveRecord::Base
belongs_to :organization
validates_presence_of :organization
end
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::Base
has_many :users
accepts_nested_attributes_for :users
def users_attributes_with_self_assignment=(attributes)
self.users_attributes_without_self_assignment = attributes
users.each { |u| u.organization = self }
end
alias_method_chain :users_attributes=, :self_assignment
end
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.