验证关联对象(惰性验证)
Posted
技术标签:
【中文标题】验证关联对象(惰性验证)【英文标题】:Validate associated object (lazy validation) 【发布时间】:2016-11-24 13:54:25 【问题描述】:我正在尝试使用条件解决关联对象的验证问题。
用户在成为作者之前无需填写author_bio
。所以应用程序需要确保作者不能在没有author_bio
的情况下创建帖子,如果用户已经创建了任何帖子,则author_bio
不能被删除。
class User < ApplicationRecord
has_many :posts, foreign_key: 'author_id', inverse_of: :author
validates :author_bio, presence: if: :author?
def author?
posts.any?
end
end
class Post < ApplicationRecord
belongs_to :author, class_name: 'User', inverse_of: :posts, required: true
end
不幸的是,这并不能验证作者是否可以创建新帖子:
user = User.first
user.author_bio
=> nil
post = Post.new(author: user)
post.valid?
=> true
post.save
=> true
post.save
=> false
post.valid?
=> false
那么如何防止用户在没有author_bio
的情况下创建新帖子?我可以向Post
模型添加第二个验证,但这不是 DRY。有没有更好的解决方案?
【问题讨论】:
【参考方案1】:这里的答案似乎是使用validates_associated
,一旦您正确设置了关联(包括您拥有的inverse_of
,但对其他人来说,rails 在许多情况下会错过它们或错误地创建它们)
所以在这里调整类:
class User < ApplicationRecord
has_many :posts, foreign_key: 'author_id', inverse_of: :author
validates :author_bio, presence: if: :author?
def author?
posts.any?
end
end
class Post < ApplicationRecord
belongs_to :author, class_name: 'User', inverse_of: :posts
validates :author, presence: true
validates_associated :author
end
现在,当您尝试运行之前的操作时:
user = User.first
user.author_bio
=> nil
post = Post.new(author: user)
post.valid?
=> false
post.save
=> false
不允许您保存,因为author_bio
为空
唯一需要注意的是建立正确的关联,否则 rails 会感到困惑并跳过User
类的验证,因为它认为这种关系还不存在。
注意:我从 belongs_to
中删除了 required: true
,因为在 rails 5 中是默认设置,因此您也不需要 validates :author, presence: true
,仅在 rails 5 中。
【讨论】:
以上是关于验证关联对象(惰性验证)的主要内容,如果未能解决你的问题,请参考以下文章
定递归验证关联的对象可以用于继承对象吗 spring validate