簡體   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