[英]Rails: querying associations during validation
在验证期间,我想查询关联,但由于 ActiveRecord 的验证风格,这两种解决方案似乎都不是很好。 这是一个例子:
class User < ApplicationRecord
has_many :borrowed_books
validate :should_only_borrow_good_books
def should_only_borrow_good_books
# What I want but it does not work:
#
# unless borrowed_books.where(condition: "bad").empty?
# errors.add(:borrowed_books, "only good books can be borrowed")
# end
#
# ^ this query always returns an empty array
# This approach works but it's not ideal:
unless borrowed_books.all? { |b| b.condition == "good" }
errors.add(:borrowed_books, "only good books can be borrowed")
end
end
end
class BorrowedBook < ApplicationRecord
belongs_to :user
# attr: condition - ["bad", "good"]
end
另一种选择是将验证移至BorrowedBook
,使用类似validates :condition, inclusion: { in: %w(good) }, if: -> { user_id.present? }
并可能在User
中验证关联,例如validates_associated :borrowed_books
validates :condition, inclusion: { in: %w(good) }, if: -> { user_id.present? }
但我不喜欢这种方法,因为它通过将属于User
的逻辑移动到BorrowedBook
使事情复杂化。 像这样的一些验证,你的应用程序可能会变得非常混乱。
这种验证绝对应该保留在用户模型中。 我不同意如果有多个条件它会看起来很乱。 如果它变得混乱,通常表明您应该拆分模型或在那里重构代码。 模型工作使您能够访问和验证来自 db 的数据。 改进当前代码的一种方法是将条件列转换为枚举,参考:https ://api.rubyonrails.org/v5.1/classes/ActiveRecord/Enum.html 可以这样写
class User < ApplicationRecord
has_many :borrowed_books
validate :should_only_borrow_good_books
private
def should_only_borrow_good_books
return unless books.not_good.any?
errors.add(:borrowed_books, "only good books can be borrowed")
end
end
end
class BorrowedBook < ApplicationRecord
belongs_to :user
enum status: [ :good, :bad ]
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.