Nested attributes in rails 2.3.3 can really simplify the updating of nested models, but creating nested models throws up an interesting problem when your model uses validates_presence_of... at least it does for me...
Lets say I have two models, a User and an Account. The User accepts nested attributes for the Account, while the Account requires the presence of a user_id.
E.g.
class User < ActiveRecord::Base has_many :accounts accepts_nested_attributes_for :accounts ... end
class Account < ActiveRecord::Base belongs_to :user validates_presence_of :user_id ... end
Now when I go to create a new user and account, up pops a validation error:
ActiveRecord::RecordInvalid: Validation failed: Accounts user can't be blank
It doesn't take much to work out that the error is due to the account object being saved before the user object - i.e. the user doesn't yet exist in the database and so doesn't have a user_id. This causes the validates_presence_of :user_id clause in the account model to fail.
I thought about simply removing the check for user_id but my user and account objects are part of a legacy system - i.e. they're used in other places and I don't want to risk removing validations that are probably required.
So what to do?
The solution I'm going with is to conditionally validate the presence of the user_id - i.e. require the validation only if the account object is being created as part of a dependent creation of a user object.
I've modified my code to set an attribute :new_user on the account when creating a new user with nested account, then check for this attribute as follows:
class Account < ActiveRecord::Base belongs_to :user validates_presence_of :user_id, :unless => :new_user attr_accessor :new_user ... end
That seems to do the trick - the validation message disappears and I'm able to create new users with embedded accounts.
Hopefully this issue will be fixed in a future version of rails. Until then... does anyone have a better solution I could use?
nested attributes | ActiveRecord | validation
Comments
| Robert said on 4-Feb-2010: |
| Thanks, it worked for me! |