3

現在の状態に応じて異なるバリデーターを必要とするモデルがあります。インスタンスごとにActiveRecordバリデーターを呼び出すにはどうすればよいですか?できるだけ多くの配管を再利用したいのですが、どうすればいいのかわかりません。

class Order < ActiveRecord::Base
  attr_accessible :state

  validate :state_specific_validations

  def state_specific_validations
    if :paid == self.state
      # Warning: here be Unicorns...

      # Wishful thinking...
      validate_presence_of :paid_at
      validate_associated :purchaser

      # Hopeful. What are the validators called internally in Rails?
      errors << PresenceValidator.new(self, :paid_at).valid?
      errors << AssociationValidator.new(self, :paid_at).valid?

      # Plan B
      # ... Hoping for help from the audience ...

    else
      # Even more complicated validator logic, hoping for some DRY validators
    end
  end
end

カスタムバリデーターを使用することもできますが、組み込みのバリデーターロジック(i18nエラーメッセージなど)をすべて複製する必要があるのはなぜですか?

Railsバリデーターをインスタンスメソッドとして呼び出すための適切な方法はありますか?SequelのインスタンスベースのバリデーターのアプローチはActiveRecordのクラスベースのアプローチよりも合理的だと思いますが、私はここで判断するつもりはありません。もっと興味深い問題の解決に戻りたいと思います。他の人がこれに出くわし、興味深い要点や宝石を教えてくれることを願っています。

4

2 に答える 2

4

validate_*すべてのメソッドがオプションをとることができると確信してい:ifます-別のメソッドを指すことができる(そしておそらくProcも受け入れる)ので、検証を次のように分割することができます:

validates_presence_of :paid_at, :if => :paid?
validates_association :purchaser, :if => :paid?

さらにクリーンアップするために、with_optionsヘルパーがあります。

with_options :if => :paid? do |v|
  v.validates_presence_of :paid_at
  v.validates_association :purchaser
end

どちらかが標準で使用できるかどうかはわかりvalidate :custom_validate_methodませんが、驚くことではありません。

于 2011-08-15T10:04:52.090 に答える
0

これが不適切な理由はありますか?うまくいくようですが、メタプログラミングが私の脳を歪めたのかもしれません...

class Order < ActiveRecord::Base
  attr_accessible :state

  validate :state_specific_validations

  def state_specific_validations
    if :paid == self.state
      class << self
        validate_presence_of :paid_at
        validate_associated :purchaser
      end
    end
  end
end

最悪の部分は、テストに合格していることです。そのため、それを解決したのか、より良いテストが必要なのかわかりません。たとえば、このシングルトン変更が他の注文に影響を与えないことを100%肯定しているわけではありません。

ため息をつく必要があります。

于 2011-08-17T19:20:31.037 に答える