我正在使用Ruby on Rails v3.2.2。我想在使用accepts_nested_attributes_for
和validates_associated
RoR方法时解决与验证外键有关的问题。也就是说,我有以下模型类:
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
...我有以下控制器操作:
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
使用上面的代码(Nested Model Form Part 1 Rails Cast的“灵感”)我的意图是在创建文章时存储类别关联( note :category对象已经存在于数据库中;在我的例子中,我想只存储 - 创建类别关联)。但是,当我从相关的视图文件中提交相关表单时,我收到以下错误(我正在记录错误消息):
{:"category_associations.article_id"=>["can't be blank"], :category_associations=>["is invalid"]}
自validates_associated
seems运行方法article.category_association.valid?
以来,为什么会发生这种情况,但前提是article.category_association.article_id
不是 nil
?如何通过article_id
外键的存在验证来解决问题?
但是,如果我在validates :article_id, :presence => true
模型类中注释掉CategoryAssociation
,它会按预期工作,但it seems to be not a right approach to do not validate foreign keys。
如果我在validates_associated :category_associations
模型类中注释掉Article
,我仍然会收到错误:
{:"category_associations.article_id"=>["can't be blank"]}
答案 0 :(得分:41)
使用inverse_of
链接关联,然后验证关联对象的存在,而不是实际外键的存在。
来自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
答案 1 :(得分:0)
由于您有一个可能的嵌套表单,其中包含accepts_nested_attributes_for,因此在CategoryAssociation中,您需要使验证成为有条件的,要求仅存在仅用于更新:
validates :article_id, presence: true, on: :update
除Active Record关联外,您应该在db级别具有外键约束。
答案 2 :(得分:0)
如果您也遇到此类错误,请尝试更换:
validates :article_id, :presence => true
validates :category_id, :presence => true
与:
validates :article, :presence => true
validates :category, :presence => true
为我工作。
答案 3 :(得分:-2)
验证将在create
或save
上运行(正如您所期望的那样),因此请问自己,“其中每个都有 已保存 实例被引用?“,因为没有保存,实例将没有id,因为它是分配id的数据库。
编辑:就像我在评论中所说的那样,如果你要进行投票,那就留下评论原因。