簡體   English   中英

Rails 模型屬性在自定義驗證器方法中為零

[英]Rails model attribute is nil in custom validator method

我有一個多態表,我希望能夠驗證創建時提供的實體 id 確實引用了現有對象。 我編寫了一個自定義驗證器來執行此操作,當我調用find_or_create_by時會調用它。 但是,我正在對其執行驗證的屬性在驗證方法中為零。

  validate :validate_id, on: :create
...

  def validate_id
    klass = Object.const_get(entity_type)

    return if klass.exists?(entity_id)

    errors.add(:entity_id, 'is invalid')
  end

entity_typeentity_id都是模型成員,並作為參數傳遞給find_or_create_by 我不明白為什么它們在驗證方法中為零。

這些值在您的方法中不包含任何內容的原因是因為它們僅適用於該方法,並且該方法不會將它們作為參數。 完成您要做的事情的最佳方法是編寫一個適當的自定義驗證器,該驗證器繼承自ActiveModel::EachValidator並實現validate_each(record, attribute, value)方法。

盡管您可以擺脫validates_each塊:

validates_each :entity_id do |record, attr, value|
  return if Entity.exists?(value)
  errors.add(attr, 'is invalid')
end

然而...

為什么不直接使用普通的包含驗證器?
因為我現在在 Rails 4.2 上,所以當Entity記錄數足夠低以至於不會導致性能問題時,我就是這樣做的。
(我會使用更好的錯誤消息,但為了簡單起見使用你的。)

  validates :entity_id,
            inclusion: { in:      proc { Entity.all.pluck(:id) },
                         message: 'is invalid' }

編輯:我現在看到的問題是您的多態實體意味着上面的示例在沒有一些調整的情況下將無法工作,因為Entity可能是EntityOneEntityTwo兩個模型中的任何一個。 您可以輕松地檢查其中任何一個是否包含有問題的 ID,如下所示:

validates_each :entity_id do |record, attr, value|
  return if EntityOne.exists?(value) || EntityTwo.exists?(value)
  errors.add(attr, 'is invalid')
end

或者

  validates :entity_id,
            inclusion: { in:      proc { EntityOne.all.pluck(:id) + EntityTwo.all.pluck(:id) },
                         message: 'is invalid' }

但這不是一個很好的驗證,因為有無效的情況作為有效傳遞。

您可能不得不求助於從ActiveModel::Validator繼承並實現validate(record)方法的適當自定義驗證器,該方法還接受您可以傳入預期實體類型的options 它看起來像這樣:

# Inside the model:
validates_with(EntityIdValidator, expected_entity: entity_type)



#The custom validator:
class EntityIdValidator < ActiveModel::Validator

  def validate(record)
    expected_entity = options[:expected_entity]
    return if expected_entity.exists?(record.entity_id)

    record.errors.add(:entity_id, 'is invalid')
  end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM