4

我有以下軌道/紙夾驗證:的Ruby/Rails繼承,覆蓋在子類中的超類中定義的驗證

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方式使用驗證器嗎?我應該如何在上述情況下使用驗證器?

回答

0

當您從超類繼承時,您也可以從中獲取驗證器。我並不十分確定這一點,但我認爲你只需將新的驗證器添加到舊的驗證器列表中,即兩個約束都適用。

我認爲最簡單的解決方案是將公共邏輯放在模塊中或從一個公共超類繼承。你也可以做這樣的事情,但我認爲這很難看:

class Superclass 
    with_options :unless => Proc.new { |a| a.validators.any? } do |super_validators| 
     super_validators.validates :password, :length => { :minimum => 10 } 
    end 
end 
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