的Rails 3:使用composed_of与验证导致ActiveRecord的错误
问题描述:
我使用以下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不适合。这是否正确,如果有,是否有解决方法?
答
不知道您是否曾经找到过解决方案,但是我可以通过向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
你是正确的,但不幸的是,我没有你的解决方案。自从我写的宝石出现同样的问题以来,我一直试图找出这个问题。 – 2012-02-05 04:00:28
解决方案并不简单。我认为它涉及到重新打开IPAddr并添加“include ActiveRecord :: Validations”,但还有很多不足之处。一旦你这样做了,你还必须添加一些方法,Rails希望ActiveRecord :: Base类具有,我认为你必须重写唯一性验证器的某些部分。如果我有时间,我可能会尝试解决这个问题,并在明天提供答案,但我不能做出任何承诺。也许这足以帮助你取得一些进展。 – Ryan 2012-02-05 07:58:32
@Ryan你有没有想过解决这个问题?你发布了一些想法,我很好奇,如果你有它的任何地方。 – 2012-04-24 01:45:37