Does anyone know if Rails is supposed to validate associated objects on
creation?
Say you have a User model, with has_many posts, and a Post model which
belongs_to user. Further, the Post model has a validates_uniqueness_of
:title.
u = User.find(1)
this should pass
u.posts.create :title => ‘my new post title’
this should fail
u.posts.create :title => ‘my new post title’
The line that should fail is actually passing, giving a u.posts.size ==
2.
if you notice…the second post is not saved and there is an error:
u = User.create(:name => ‘Chris’)
=> #<User:0xb78541f4 @new_record_before_save=false, @new_record=false,
@errors=#<ActiveRecord::Errors:0xb784a49c @errors={},
@base=#<User:0xb78541f4 …>>, @attributes={“name”=>“Chris”, “id”=>1}>
u.posts.create :title => ‘My First Post’
=> #<Post:0xb7844060 @new_record=false,
@errors=#<ActiveRecord::Errors:0xb78428b4 @errors={},
@base=#<Post:0xb7844060 …>>, @attributes={“body”=>"", “title”=>“My
First
Post”, “id”=>1, “user_id”=>1}>
u.posts.create :title => ‘My First Post’
=> #<Post:0xb783c428 @new_record=true,
@errors=#<ActiveRecord::Errors:0xb783ba50 @errors={“title”=>[“has
already
been taken”]}, @base=#<Post:0xb783c428 …>>, @attributes={“body”=>"",
“title”=>“My First Post”, “user_id”=>1}>
notice @errors above: @errors={“title”=>[“has already been taken”]},
posts = Post.find(:all)
=> [#<Post:0xb7837be4 @attributes={“title”=>“My First Post”, “body”=>"",
“id”=>“1”, “user_id”=>“1”}>]
and notice that it was not saved, as per the validation
u.posts
=> [#<Post:0xb7844060 @new_record=false,
@errors=#<ActiveRecord::Errors:0xb78428b4 @errors={},
@base=#<Post:0xb7844060 …>>, @attributes={“body”=>"", “title”=>“My
First
Post”, “id”=>1, “user_id”=>1}>, #<Post:0xb783c428 @new_record=true,
@errors=#<ActiveRecord::Errors:0xb783ba50 @errors={“title”=>[“has
already
been taken”]}, @base=#<Post:0xb783c428 …>>, @attributes={“body”=>"",
“title”=>“My First Post”, “user_id”=>1}>]
but also notice that it DOES exist as a new record in the posts
collection.
that’s expected behavior.
when create fails, the object is still instantiated, just not saved to
the
db.