验证外键时accept_nested_attributes_for有问题

时间:2012-11-12 12:52:18

标签: ruby-on-rails validation activerecord associations

我正在使用Ruby on Rails v3.2.2。我想在使用accepts_nested_attributes_forvalidates_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"]}

4 个答案:

答案 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)

验证将在createsave上运行(正如您所期望的那样),因此请问自己,“其中每个都有 已保存 实例被引用?“,因为没有保存,实例将没有id,因为它是分配id的数据库。


编辑:就像我在评论中所说的那样,如果你要进行投票,那就留下评论原因。