Rails - 如何验证外键引用的行的存在

时间:2012-06-16 09:25:20

标签: ruby-on-rails-3 foreign-keys

鉴于“Rails Way”似乎不使用外键约束,我正在寻找一种替代方案,允许我在保存之前验证外键引用的行实际上存在于TableA中表B中的对象与table_a_id。

到目前为止我发现的唯一资源(无法找到它在2007年提到的博客文章的链接)似乎与Rails 3.2不兼容,所以任何人都可以建议这样做的方法?

我目前正在考虑创建一个验证器来手动分配给我的模型中的相关属性,但我无法弄清楚如何使用validate_each(对象,属性,值)来完成它。

6 个答案:

答案 0 :(得分:32)

只需使用如下,

validates :user, presence: true

它会自动检查数据库中是否存在用户记录。

答案 1 :(得分:6)

有一个插件可以帮助您解决 belongs_to 关联:Validates existence of。但是,也许你可以添加自己的验证?这样的事情怎么样:

# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists

def user_id_exists
  return false if User.find_by_id(self.user_id).nil?
end

答案 2 :(得分:4)

我对这段代码有疑问:

return false if User.find(self.user_id).nil?

当找不到匹配的记录时,我必须捕获ActiveRecord异常。当没有找到记录时, nil?不起作用;在执行 nil?之前抛出异常。

# Assuming your foreign key is user_id (which references the table User)
validate :user_id_exists

def user_id_exists
  begin
    User.find(self.user_id)
  rescue ActiveRecord::RecordNotFound
    errors.add(:user_id, "user_id foreign key must exist")
    false
  end
end

在单元测试中使用无效?断言时,这很有用。

request.user_id = unknown
assert request.invalid?

request.user_id = 1
assert request.valid?

答案 3 :(得分:3)

请注意,从Rails 3.2开始,validates_presence_of在这种情况下完全按照您希望的方式工作,您不必像上面的答案那样构建复杂的结构,甚至不需要使用nice validates_existence_of gem。

答案 4 :(得分:1)

我不喜欢异常。我这样解决了这个问题:

class Foo < ActiveRecord::Base

    validate :bar_exists

    protected

    def bar_exists
        if !User.where(bar_id: self.bar_id).exists? then
            errors.add(:bar_id, 'A valid bar_id is valid.')
        end
    end

end

答案 5 :(得分:1)

您需要指定inverse_of选项并验证其存在是否为真。

来自Active Record Validations Guide

  

为了验证需要存在的相关记录,   您必须为关联指定:inverse_of 选项