4

私は次のレール/ペーパークリップバリデーターを持っています:

class ImageRatioValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    attr_name = "#{attribute}_width".to_sym
    value = record.send(:read_attribute_for_validation, attribute)
    valid_ratios = options[:ratio]

    if !value.queued_for_write[:original].blank?
      geo = Paperclip::Geometry.from_file value.queued_for_write[:original]

      # first we need to validate the ratio
      cur_ratio = nil
      valid_ratios.each do |ratio, max_width|
        parts = ratio.split ":"
        next unless (geo.height * parts.first.to_f) == (geo.width * parts.last.to_f)
        cur_ratio = ratio
      end
      # then we need to make sure the maximum width of the ratio is honoured
      if cur_ratio
        if not valid_ratios[cur_ratio].to_f >= geo.width
          record.errors[attribute] << "The maximum width for ratio #{cur_ratio} is #{valid_ratios[cur_ratio]}. Given width was #{geo.width}!"
        end
      else
        record.errors[attribute] << "Please make sure you upload a stall logo with a valid ratio (#{valid_ratios.keys.join(", ")})!"
      end
    end
  end
end

バリデーターは、スーパー (スーパークラスは抽象的ではないため、インスタンス化できます) とサブクラスの両方で使用されます。サブクラスでは、許可されている比率を変更する必要があります。

スーパークラス:

class Superclass
    validates_attachment :logo, :image_ratio => { :ratio  => {"1:1" => "28", "4:1" => "50", "5:1" => "40"} }
end

サブクラス:

class Subclass < Superclass
  validates_attachment :logo, :image_ratio => { :ratio  => {"1:1" => "40", "2:1" => "60"} }
end

バリデーターはスーパークラスで期待どおりに機能しますが、サブクラスで指定された新しい比率を無視しているようです。
Rails 以外の方法でバリデーターを使用しようとしていますか? 上記のような状況でバリデーターをどのように使用すればよいですか?

4

2 に答える 2

0

これは解決策として理想的ではありませんが、かなりクリーンです。

タイプに基づいてカスタム検証を使用するだけです。このようにして、両方のバリデーターをスーパー クラスで定義しますが、確実に機能します。

class Superclass
    validates_attachment :logo, :image_ratio => { :ratio  => {"1:1" => "28", "4:1" => "50", "5:1" => "40"} }, :if => self.is_a?(SuperClass)
    validates_attachment :logo, :image_ratio => { :ratio  => {"1:1" => "40", "2:1" => "60"} }, :if => self.is_a?(SubClass)
end
于 2012-11-19T09:53:22.733 に答える
0

スーパークラスから継承すると、そこからバリデーターも取得されます。これについて 100% 確信があるわけではありませんが、古いバリデータのリストに新しいバリデータを追加するだけでよいと思います。つまり、両方の制約が適用されます。

最も簡単な解決策は、共通のロジックをモジュールに入れるか、共通のスーパークラスから継承することだと思います。次のようなこともできますが、かなり醜いと思います。

class Superclass
    with_options :unless => Proc.new { |a| a.validators.any? } do |super_validators|
        super_validators.validates :password, :length => { :minimum => 10 }
    end
end
于 2012-07-27T01:13:33.337 に答える