Reputation: 4792
I am using Ruby on Rails v3.2.2. I would like to solve the issue related to the validation of a foreign key when using accepts_nested_attributes_for
and validates_associated
RoR methods. That is, I have following model classes:
class Article < ActiveRecord::Base
has_many :category_associations, :foreign_key => 'category_id'
accepts_nested_attributes_for :category_associations, :reject_if => lambda { |attributes| attributes[:category_id].blank? }
validates_associated :category_associations
end
class CategoryAssociation < ActiveRecord::Base
belongs_to :article, :foreign_key => 'article_id'
belongs_to :category, :foreign_key => 'category_id'
validates :article_id, :presence => true
validates :category_id, :presence => true
end
... and I have following controller actions:
class ArticlesController < ApplicationController
def new
@article = Article.new
5.times { @article.category_associations.build }
# ...
end
def create
@article = Article.new(params[:article])
if @article.save
# ...
else
# ...
end
end
end
With the above code ("inspired" by the Nested Model Form Part 1 Rails Cast) my intent is to store category associations when creating an article (note: category objects are already present in the database; in my case, I would like just storing-creating category associations). However, when I submit the related form from the related view file, I get the following error (I am logging error messages):
{:"category_associations.article_id"=>["can't be blank"], :category_associations=>["is invalid"]}
Why it happens since validates_associated
seems to run the method article.category_association.valid?
but only if the article.category_association.article_id
is not nil
? How can I solve the problem with the presence validation of the article_id
foreign key?
However, if I comment out the validates :article_id, :presence => true
in the CategoryAssociation
model class, it works as expected but it seems to be not a right approach to do not validate foreign keys.
If I comment out the validates_associated :category_associations
in the Article
model class, I still get the error:
{:"category_associations.article_id"=>["can't be blank"]}
Upvotes: 30
Views: 8782
Reputation: 1
If you're stucked with this kind of errors too, try to replace:
validates :article_id, :presence => true
validates :category_id, :presence => true
with:
validates :article, :presence => true
validates :category, :presence => true
worked for me.
Upvotes: 0
Reputation: 5847
Use inverse_of
to link the associations and then validate the presence of the associated object, not the presence of the actual foreign key.
Example from the docs:
class Member < ActiveRecord::Base
has_many :posts, inverse_of: :member
accepts_nested_attributes_for :posts
end
class Post < ActiveRecord::Base
belongs_to :member, inverse_of: :posts
validates_presence_of :member
end
Upvotes: 45
Reputation: 4270
Since you have a possible nested form with accepts_nested_attributes_for, therefore in CategoryAssociation you need to make the validation conditional, requiring presence for only for only updates:
validates :article_id, presence: true, on: :update
Aside from Active Record associations, you should have a foreign key constraints at the db level.
Upvotes: 0
Reputation: 12251
Validations will run on create
or save
(as you'd expect), so ask yourself, "at each one of those is there a saved instance being referred to?", because without a save an instance won't have an id as it's the database that assigns the id.
Edit: Like I've said in the comments, if you're going to downvote then leave a comment as to why.
Upvotes: -2