30

我正在使用 Ruby on Rails v3.2.2。我想解决与使用accepts_nested_attributes_forvalidates_associatedRoR 方法时外键验证相关的问题。也就是说,我有以下模型类:

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

使用上面的代码(受嵌套模型表单第 1 部分Rails Cast 的“启发”) ,我的意图是在创建文章时存储类别关联注意:类别对象已经存在于数据库中;在我的情况下,我只想存储-创建类别关联)。但是,当我从相关视图文件提交相关表单时,我收到以下错误(我正在记录错误消息):

{:"category_associations.article_id"=>["can't be blank"], :category_associations=>["is invalid"]}

为什么它会发生,因为它validates_associated 似乎运行了该方法article.category_association.valid?,但只有在article.category_association.article_idis not nil的情况下?如何解决article_id外键存在验证的问题?

validates :article_id, :presence => true但是,如果我在模型类中注释掉CategoryAssociation,它会按预期工作,但它似乎不是验证外键的正确方法


validates_associated :category_associations如果我在模型类中注释掉Article,我仍然会收到错误:

{:"category_associations.article_id"=>["can't be blank"]}
4

4 回答 4

45

用于inverse_of链接关联,然后验证关联对象的存在,而不是实际外键的存在。

文档中的示例:

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
于 2013-05-28T13:54:42.703 回答
0

由于您有一个带有accepts_nested_attributes_for 的可能嵌套表单,因此在CategoryAssociation 中您需要使验证成为有条件的,仅对更新要求存在:

validates :article_id, presence: true, on: :update

除了 Active Record 关联之外,您还应该在 db 级别有一个外键约束。

于 2014-06-25T02:22:57.050 回答
0

如果您也遇到此类错误,请尝试替换:

validates :article_id, :presence => true
validates :category_id, :presence => true

和:

validates :article, :presence => true
validates :category, :presence => true

为我工作。

于 2021-04-05T20:19:32.300 回答
-2

验证将在createor上运行save(如您所料),所以问问自己,“在其中的每一个上都有一个保存的实例被引用吗?”,因为没有保存,实例就没有 id,因为它是数据库分配ID。


编辑:就像我在评论中所说的那样,如果您要投反对票,请发表评论以说明原因。

于 2012-11-12T14:32:57.610 回答