繁体   English   中英

Rails:在验证期间查询关联

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM