[英]Validate that the associated model exists when set in Rails
假设我们在Rails中具有以下Post
模型:
class Post < ActiveRecord::Base
belongs_to :user
end
user
不是必需的,但是在设置用户名后,我们希望它成为有效的关联(我们不希望发布的帖子中的user_id
不在数据库中)。 测试失败:
expect(Post.new).to be_valid
expect(Post.new(user_id: 0)).not_to be_valid
expect(Post.new(user: User.create)).to be_valid
一种解决方案是:
validates_presence_of :user, unless: "user_id.nil?"
这将完成所需的任务,但并不是很漂亮,因为我们不想为应用程序中的每个belongs_to
编写它。
有没有办法告诉Rails检查关联模型的存在? 这不是我们默认想要的东西吗? (为什么我们要一个不指向任何东西的association_id
?)
为了确保关联在数据库级别有效,MySQL和PostgreSQL能够强制表上外键列的有效性。 从Rails 4.2开始 ,可以在迁移过程中创建这些外键约束。
您可以在迁移中至少以两种方式执行此操作。 要么将foreign_key
属性传递给add_reference :
add_reference :posts, :user, index: true, foreign_key: true
或在add_reference
加上add_foreign_key ,这也使您可以选择在删除用户时重置密钥:
add_reference :posts, :user, index: true
add_foreign_key :posts, :user, on_delete: :nullify
通过将哈希传递给add_reference
的foreign_key
属性来组合两种方法(从Rails 4.2.1开始):
add_reference :posts, :user, index: true, foreign_key: {on_delete: :nullify}
如果查询通过更新user_id
以指向不存在的用户来打破外键约束,则查询将失败并在Rails中引发异常。
如前所述,您还可以创建一个验证以在创建Post
之前检查User
存在。 但是,这不能像数据库上的外键约束那样有力的保证,因为可以在通过验证和创建Post
之间的时间内删除User
。
为了帮助保持引用在应用程序级别上的有效性,通常最好的做法是避免将用户ID直接传递给Post
构造函数。 而是尝试始终使用User
对象作为输入,例如通过调用User.find(:id)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.