3

我使用以下code snippet from the Rails docs將它們插入到數據庫之前,IP地址到整數轉換:的Rails 3:使用composed_of與驗證導致ActiveRecord的錯誤

composed_of :user_ip, 
      :class_name => 'IPAddr', 
      :mapping => %w(user_ip to_i), 
      :constructor => Proc.new { |ip| IPAddr.new(ip, Socket::AF_INET) }, 
      :converter => Proc.new { |ip| ip.is_a?(Integer) ? IPAddr.new(ip, Socket::AF_INET) : IPAddr.new(ip.to_s) } 

的composed_of塊隨後是這種簡單的驗證:

validates_uniqueness_of :user_ip 

但反過來驗證拋出試圖創建一個新的對象時出現錯誤:

TypeError: Cannot visit IPAddr 

刪除驗證,錯誤消失。

如果我理解正確,就會發生這種情況,因爲:user_ip變爲IPAddr對象,並且ActiveRecord不適合。這是否正確,如果有,是否有解決方法?

+0

你是正確的,但不幸的是,我沒有你的解決方案。自從我寫的寶石出現同樣的問題以來,我一直試圖找出這個問題。 – 2012-02-05 04:00:28

+0

解決方案並不簡單。我認爲它涉及到重新打開IPAddr並添加「include ActiveRecord :: Validations」,但還有很多不足之處。一旦你這樣做了,你還必須添加一些方法,Rails希望ActiveRecord :: Base類具有,我認爲你必須重寫唯一性驗證器的某些部分。如果我有時間,我可能會嘗試解決這個問題,並在明天提供答案,但我不能做出任何承諾。也許這足以幫助你取得一些進展。 – Ryan 2012-02-05 07:58:32

+0

@Ryan你有沒有想過解決這個問題?你發佈了一些想法,我很好奇,如果你有它的任何地方。 – 2012-04-24 01:45:37

回答

2

不知道您是否曾經找到過解決方案,但是我可以通過向Arel添加訪問方法將其修補到我的寶石中。

你應該可以做下面的事情來實現它。這是根據Arel converts values如何用於其他類型的對象如日期。不知道你是否需要將該值轉換爲字符串,但它可能只是一個整數。

module Arel 
    module Visitors 
    class ToSql 
     def visit_IPAddr 
     quote(value.to_i) 
     end 
    end 
    end 
end 

我需要能夠動態生成這些方法,所以我用我的寶石如下:

Arel::Visitors::ToSql.class_eval do 
    define_method "visit_#{klass.name}", lambda {|value| quote(value.to_s) } 
end 
+0

感謝分享。我從來沒有打算找到解決方案,但如果我今天要嘗試,我會放棄IPAddr,並嘗試使用注入方法轉換IP(無論如何,它的工作更快) – Marco 2012-04-29 23:17:48

+0

「visit_IPAddr」的簽名取決於您需要支持的Arel版本。在Arel 4.0.2(在Rails 4.0中使用)中,它應該是'visit_IPAddr(object,attribute)',最遲應該是'visit_IPAddr(object)'。無論哪種情況,在方法中使用給定的'object'而不是'value'。 – Brandan 2014-12-19 19:39:24

相關問題