Geocoder rails,检查是否有效

时间:2014-04-15 17:22:01

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

以下是我使用地理编码器的课程。我无法检查通过地理编码器发送的地址是否有效。当我添加公司/编辑公司时,此代码非常有用,该公司的地址通过地理编码器提供经度和纬度。但是我需要代码才能工作,所以当用户试图在编辑或创建公司时放置一个不给出纬度和经度的地址时,会弹出一个错误并通知用户该地址无效。

模型

class Company < ActiveRecord::Base
    validates :name, presence: true, length: { maximum: 30 }
    validates :website, presence: true
    validates :address, presence: true
    validates :description, presence: true
    validates :primary_field, presence: true

    geocoded_by :address
    before_save :geocode, if: ->(obj){ obj.address.present? and obj.address_changed? }

    after_save :set_popup_value

    private

     ...

end

查看

<% provide(:title, 'Add Company') %>
<h1>Add Company</h1>
<div class="row">
  <div class="span6 offset3">
    <%= form_for(@company) do |f| %>
      <%= render 'shared/error_messages' %>

      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :website %>
      <%= f.text_field :website %>

      <%= f.label :primary_field %>
      <%= f.select :primary_field, @primary_field %>

      <%= f.label :address %>
      <%= f.text_field :address, :placeholder => '123 Test St, City State Zip'%>

      <%= f.label :description %>
      <%= f.text_area :description, :size => "30x5" %>

      <%= f.submit "Add Company", class: "btn btn-large btn-primary" %>
    <% end %>
  </div>
</div>

5 个答案:

答案 0 :(得分:3)

所以,几天来我已经能够修补这个问题了,我想出了几个解决方案。第一个真的很hacky,但完成了我需要的。我的第二个解决方案更加优雅,并且从我迄今为止所能说的方面来说效果很好!我希望其他人觉得这很有用。

我只用几行处理控制器中的所有逻辑。

geocoded_by :address
after_validation :geocode, if: ->(obj){ obj.address.present? and obj.address_changed? }
after_validation :lat_changed?

after_save :set_popup_value

private

# This is used to make sure that our address is actually parsed properly and we
# get a valuable lat/long
def lat_changed?
    if (self.address_changed?)
        if !(self.latitude_changed?)
            self.errors.add(:address, "is not valid")
            return false
        end
    end
    return true
end

通过在我的地理编码之后创建另一个after_validation,我能够检查相应的值是否已更改,以及它们是否以某种方式更改,而不是我知道地理编码中存在问题。

如果地址发生变化,但纬度没有变化,那么你知道当地址通过地理编码器时它没有得到返回的纬度/经度。如果是这种情况,那么我们只是添加一个错误扔给用户并返回false,这将停止保存到数据库。

我希望有这个问题的其他人能够找到这篇文章!

答案 1 :(得分:1)

您可能想要对地理编码服务进行网络/服务调用。你如何做到这一点取决于你想要什么:ajaxy请求或后台工作等。

对于SO来说,这是一个非常普遍的问题,你可能会在programmers.stackexchange.com中获得更好的牵引力。

但是,这里有一些链接可以帮助你:

Google地理编码API:https://developers.google.com/maps/documentation/geocoding/?csw=1

OpenStreetMap:http://wiki.openstreetmap.org/wiki/Nominatim#Reverse_Geocoding_.2F_Address_lookup

答案 2 :(得分:1)

由于您正在使用Geocoder,因此您需要有机会在保存之前检查地理编码器的结果。此过程在“{3}}中的”高级地理编码“部分进行了解释。举一个例子,你可以这样做:

geocoded_by :address do |obj,results|
  ....
end

验证结果后,如果您尚未获得坐标,则可以使您的异常/添加验证错误/无论如何。

当然这意味着,您必须调用Web服务才能看到,如果地址正常 - 就像其他人所说的那样,在此之前完成一些基本验证会很不错。

答案 3 :(得分:1)

您可以在下面的示例中设置模型以验证address geocode只会在地址更改时调用一次。 在geocoded_by方法中,我们明确设置为latitudelongitude,因此,当找不到地址时,这些列将设置为nil

class Company < ActiveRecord::Base
   geocoded_by :address do |object, results|
    if results.present?
     object.latitude = results.first.latitude
     object.longitude = results.first.longitude
    else
     object.latitude = nil
     object.longitude = nil
    end
  end

  before_validation :geocode, if: :address_changed?

  validates :address, presence: true
  validates :found_address_presence

  def found_address_presence
    if latitude.blank? || longitude.blank?
      errors.add(:address, "We couldn't find the address")
    end
  end
end

答案 4 :(得分:0)

Sean Callahan说的还可以。您可以改进代码:

def lat_changed?
  if address_changed? && !latitude_changed?
    self.errors.add(:address, "is not valid")
  end
end

没有必要返回true / false