Rails在模型中以两种方式进行地理编码

时间:2013-02-11 01:19:53

标签: ruby-on-rails ruby ruby-on-rails-3 rails-geocoder

我正在使用地理编码器,并有一个名为Location的模型。此模型包含经度,纬度和地址。我想要的是为用户提供填写经度和纬度或地址的选项。如果其中一个填满,则填写剩余的信息。所以我在这里做了什么

  before_validation :check
  def check
    if self.address.blank?
        reverse()
    else
        geo()
    end
  end

  def reverse
    reverse_geocoded_by :latitude, :longitude,
    :address => :address
    after_validation :reverse_geocode
  end

  def geo
    geocoded_by :address
    after_validation :geocode
  end

但我得到以下undefined method reverse_geocoded_by我不知道该怎么做!

1 个答案:

答案 0 :(得分:2)

您无法在实例方法中调用类方法。请记住,geocoded_by可能是为您的模型类定义的。您不能在不影响模型的所有实例的情况下随意更改一个实例的验证,因此通常认为这是一个坏主意。

您可能最好拥有一个“位置”模型,该模型可以通过两种不同方式之一进行地理编码,并为每种编码类型创建一个子类。也就是说,可以独立地为这些中的每一个建立规则。使用单表继承(STI)可以轻松存储这些内容。

所以你可以:

class Location < ActiveRecord::Base
end

class ForwardLocation < Location
  geocoded_by :address
  after_validation :geocode
end

class ReverseLocation < Location
  reverse_geocoded_by :latitude, :longitude,
    :address => :address
  after_validation :reverse_geocode
end

然后你会相应地添加正确的位置:

self.location = self.address? ? ReverseLocation.create(...) : ForwardLocation.create(...)

您还可以编写处理填充字段的方法,而不是像这样使用子类,但它完全取决于您接收和处理的数据类型。

通常,一个类应该只有一组前/后回调。如果回调定义支持:if样式声明,它可以有条件地触发其中一些回调。有时您需要编写自己的before_validation例程来处理更多奇特的需求。