Rails 3:使用composition_of和验证会导致ActiveRecord错误

时间:2012-02-05 01:31:23

标签: ruby-on-rails ruby-on-rails-3 validation activerecord ip-address

我使用以下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) }

然后,通过这个简单的验证,使用composed_of块:

validates_uniqueness_of :user_ip

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

TypeError: Cannot visit IPAddr

删除验证,错误消失。

如果我理解正确,就会发生这种情况,因为:user_ip成为IPAddr对象,而且不适合ActiveRecord。这是正确的,如果是这样,有没有办法绕过它?

1 个答案:

答案 0 :(得分:2)

不确定您是否找到了解决方案,但我可以通过向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