【问题标题】:Geocoder rails, check if valid地理编码器导轨,检查是否有效
【发布时间】:2014-05-30 04:53:21
【问题描述】:

下面是我使用地理编码器的课程。我无法检查通过地理编码器输入的地址是否有效。当我添加公司/编辑具有地址的公司时,此代码效果很好,当通过地理编码器提供纬度和经度时。但是我需要代码才能工作,因此当用户尝试在编辑或创建公司时输入不提供纬度和经度的地址时,会弹出错误并通知用户该地址无效。

型号

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>

【问题讨论】:

  • 你是要SO给你写地址验证码吗?
  • 不,我只是不知道在哪里/如何检查地址是否有效。所以基本上,当用户点击“添加公司”按钮时,如果用户输入的地址地理编码器无法返回经纬度,那么我需要引发错误。但我不知道该怎么做。

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


【解决方案1】:

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

这是一个非常普遍的问题,您可能会在programmers.stackexchange.com 中获得更好的牵引力

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

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

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

【讨论】:

    【解决方案2】:

    由于您使用的是地理编码器,因此您只需要在保存前检查地理编码器的结果即可。此过程在github page 中的“高级地理编码”部分中进行了说明。举个例子,你可以这样做:

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

    验证结果后,如果你还没有得到你的坐标,你可以让你的异常/添加验证错误/无论如何。

    当然,这意味着您必须调用网络服务来查看地址是否正常 - 就像其他人所说的那样,在此之前完成一些基本验证会很好。

    【讨论】:

      【解决方案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,这会停止保存到数据库。

      希望有这个问题的人也能找到这篇文章!

      【讨论】:

      • 您可以改进它:def lat_changed? ` if address_changed? && !latitude_changed?` ` self.errors.add(:address, "is not valid")` ` end` end
      • 我认为在验证回调后添加错误不是个好主意。
      • 这是一个假设,如果地址发生变化,则必须更改纬度。这一定是真的吗?
      【解决方案4】:

      Sean Callahan 说的没问题。您可以改进代码:

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

      不需要返回真/假

      【讨论】:

        【解决方案5】:

        您可以像下面这个例子一样在模型中设置addressgeocode在地址改变时只会被调用一次。 在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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-09
          相关资源
          最近更新 更多