16

鉴于“Rails 方式”似乎不使用外键约束,我正在寻找一种替代方法,允许我在将对象保存到 TableB 之前验证外键引用的行确实存在于 TableA 中与 table_a_id。

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

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

4

6 回答 6

37

只需像下面这样使用,

validates :user, presence: true

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

来自Active Record Validation 的参考 -presence

如果您想确定关联是否存在,则需要测试关联对象本身是否存在,而不是用于映射关联的外键。这样,不仅可以检查外键是否为空,还可以检查引用的对象是否存在。

于 2014-04-23T19:58:29.673 回答
8

有一个插件可以帮助您处理belongs_to关联:验证. 但是,也许您可​​以添加自己的验证?像这样的东西怎么样:

# 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
于 2012-06-16T09:36:59.987 回答
4

我对这段代码有问题:

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

当没有找到匹配的记录时,我必须捕获 ActiveRecord 异常。零?没有找到记录时不起作用;在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?
于 2012-12-30T05:06:47.140 回答
3

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

于 2013-10-25T00:24:52.747 回答
2

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

活动记录验证指南

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

于 2015-01-28T01:28:16.393 回答
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
于 2013-09-24T06:26:17.807 回答