我使用以下 code snippet from the Rails docs 将 IP 转换为整数,然后再将它们插入数据库:

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) }

然后在 composition_of 块之后是这个简单的验证:
validates_uniqueness_of :user_ip

但是在尝试创建新对象时,验证反过来会引发错误:
TypeError: Cannot visit IPAddr

删除验证,错误就消失了。

如果我理解正确,发生这种情况是因为 :user_ip 变成了 IPAddr 对象,这与 ActiveRecord 不符。这是正确的,如果是这样,有没有办法解决它?

最佳答案

不确定您是否找到了解决方案,但我能够通过向 Arel 添加访问方法在我的 gem 中修补它。

您应该能够执行以下操作以使其正常工作。这是基于 Arel converts values 如何用于其他类型的对象,例如日期。不确定是否需要将该值转换为字符串,但它可能仅用作整数。

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

我需要能够动态生成这些方法,所以我在我的 gem 中使用了以下内容:
Arel::Visitors::ToSql.class_eval do
  define_method "visit_#{klass.name}", lambda {|value| quote(value.to_s) }
end

关于ruby-on-rails - Rails 3 : using composed_of with validation causes ActiveRecord error,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9146180/

10-12 17:39
查看更多