2013-02-26 55 views
6

的順序我有我寫的是有三個驗證驗證程序類,即調用MyVariableName.valid?Rails的指定驗證

validates_length_of :id_number, :is => 13, :message => "A SA ID has to be 13 digits long" 
validates_format_of :id_number, :with => /^[0-9]+$/, :message => "A SA ID cannot have any symbols or letters" 
validate :sa_id_validator 

時,第三個是一個自定義的驗證器中運行。問題是我的驗證器sa_id_validator要求傳入的數據是13位數字,否則我會得到錯誤。我如何確保validate :sa_id_validator僅在前兩次運行後才被考慮?

對不起,如果這是一個非常簡單的問題,我試圖在昨天下午搞清楚這一點。

注:此驗證程序必須運行在一對夫婦一千項,還對上傳的電子表格,所以我需要它跑得快..

我看到了這樣的方式,但它可能運行驗證兩次,在我的情況下會很糟糕。

編輯:

我的自定義驗證程序看起來像這樣

def sa_id_validator 
    #note this is specific to South African id's 
    id_makeup = /(\d{6})(\d{4})(\d{1})(\d{1})(\d{1})/.match(@id_number) 
    birthdate = /(\d{2})(\d{2})(\d{2})/.match(id_makeup[1]) 
    citizenship = id_makeup[3] 
    variable = id_makeup[4] 
    validator_key = id_makeup[5] 

    birthdate_validator(birthdate) && citizenship_validator(citizenship) && variable_validator(variable) && id_algorithm(id_makeup[0], validator_key) 
end 

private 

def birthdate_validator(birthdate) 
    Date.valid_date?(birthdate[1].to_i,birthdate[2].to_i,birthdate[3].to_i) 
end 

def citizenship_validator(citizenship) 
    /[0]|[1]/.match(citizenship) 
end 

def variable_validator(variable) 
    /[8]|[9]/.match(variable) 
end 

def id_algorithm(id_num, validator_key) 
    odd_numbers = digits_at_odd_positions 
    even_numbers = digits_at_even_positions 
    # step1: the sum off all the digits in odd positions excluding the last digit. 
    odd_numbers.pop 
    a = odd_numbers.inject {|sum, x| sum + x} 
    # step2: concate all the digits in the even positions. 
    b = even_numbers.join.to_i 
    # step3: multiply step2 by 2 then add all the numbers in the result together 
    b_multiplied = (b*2) 
    b_multiplied_array = b_multiplied.to_s.split('') 
    int_array = b_multiplied_array.collect{|i| i.to_i} 
    c = int_array.inject {|sum, x| sum + x} 
    # step4: add the result from step 1 and 3 together 
    d = a + c 
    # step5: the last digit of the id must equal the result of step 4 mod 10, subtracted from 10 
    return false unless 
    validator_key == 10 - (d % 10) 
    end 

    def digits_at_odd_positions 
    id_num_as_array.values_at(*id_num_as_array.each_index.select(&:even?)) 
    end 

    def digits_at_even_positions 
    id_num_as_array.values_at(*id_num_as_array.each_index.select(&:odd?)) 
    end 

    def id_num_as_array 
    id_number.split('').map(&:to_i) 
    end 
end 

,如果我的:calculations_ok => true屬性添加到我的驗證,然後傳遞一個12位的數字,而不是我得到這個錯誤:

i.valid? 
NoMethodError: undefined method `[]' for nil:NilClass 
from /home/ruberto/work/toolkit_3/toolkit/lib/id_validator.rb:17:in `sa_id_validator' 

所以你可以看到它進入自定義驗證,即使它應該失敗了validates_length_of :id_number

+0

退房的答案爲http://stackoverflow.com/questions/5966055/controlling-the-order-of-rails-validations – 2013-02-26 07:13:08

+0

是的,我嘗試了所有的解決方案,並沒有似乎工作 – TheLegend 2013-02-26 07:25:57

回答

2

我不太確定,但我已經閱讀過一些博客,Rails總是運行所有驗證,即使第一個驗證無效。

你可以做的是讓你的自定義方法變得靈活或有彈性,這樣我就可以處理所有的情況。

這個answer肯定會幫助你。

希望它會回答你的問題

+0

我只是附加到我的問題。吸那個鐵軌的人跑所有的驗證,並且不會停在第一個失敗的人。 – TheLegend 2013-02-26 07:27:39

+0

不是;該模型在任何時候都應該是有效的,所以它是有道理的,軌道不會停在一個失敗的。最好遵循鏈接中的建議,並修改您的自定義驗證器以使其更加健壯。 – 2013-02-26 07:34:17

+0

@TheLegend沒有,實際上驗證的主要目的是形式助手,可以說你有一個形式,你檢查第一屬性和唯一性的第二現在如你所說如果軌道只顯示錯誤的第一個即'那麼用戶將無法看到唯一性的錯誤消息,所以它將顯示所有單一錯誤中的錯誤很有幫助。 – 2013-02-26 07:40:29