简体   繁体   English

Rails:在验证期间查询关联

[英]Rails: querying associations during validation

During validation, I want to query associations but neither solution seems to be good because ActiveRecord's style of validation.在验证期间,我想查询关联,但由于 ActiveRecord 的验证风格,这两种解决方案似乎都不是很好。 Here is an example:这是一个例子:

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

One more option is to move the validation to BorrowedBook with something like validates :condition, inclusion: { in: %w(good) }, if: -> { user_id.present? }另一种选择是将验证移至BorrowedBook ,使用类似validates :condition, inclusion: { in: %w(good) }, if: -> { user_id.present? } validates :condition, inclusion: { in: %w(good) }, if: -> { user_id.present? } and perhaps validate association in User like validates_associated :borrowed_books .并可能在User中验证关联,例如validates_associated :borrowed_books validates :condition, inclusion: { in: %w(good) }, if: -> { user_id.present? } But I don't like this approach because it complicates things by moving the logic belonging to User to BorrowedBook .但我不喜欢这种方法,因为它通过将属于User的逻辑移动到BorrowedBook使事情复杂化。 A few validations like this and your app might become really messy.像这样的一些验证,你的应用程序可能会变得非常混乱。

This validation should definitely stay in the user model.这种验证绝对应该保留在用户模型中。 I do disagree that it will look messy if there are multiple conditions.我不同意如果有多个条件它会看起来很乱。 If it makes messy, it often indicate that you should split the model or refactor the code there.如果它变得混乱,通常表明您应该拆分模型或在那里重构代码。 It's the models job to enable you to access and validate the data from db.模型工作使您能够访问和验证来自 db 的数据。 A way to improve the current code is to convert the condition column to enum, ref:https://api.rubyonrails.org/v5.1/classes/ActiveRecord/Enum.html you can write it like this改进当前代码的一种方法是将条件列转换为枚举,参考: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