验证关联对象(惰性验证)

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

如何根据 Rails 中的其他对象验证多对多关联?

如何获取满足匹配对象的关联文档

ORM增删改查(关联 | 聚合 | F/Q)&惰性机制 | Django开发

Rails validates_presence_of 并验证 has_one 关联模型中的存在