Ruby on rails 地理编码器轨道,检查是否有效
下面是我正在使用geocoder的类。我无法检查通过地理编码器输入的地址是否有效。当我添加一家公司/编辑一家公司时,这段代码非常有效,该公司的地址通过geocoder提供纬度和经度。但我需要代码来工作,这样当用户试图在编辑或创建公司时,将一个没有给出经度和纬度的地址放入时,就会弹出一个错误,并通知用户该地址无效 型号Ruby on rails 地理编码器轨道,检查是否有效,ruby-on-rails,ruby,rails-geocoder,Ruby On Rails,Ruby,Rails Geocoder,下面是我正在使用geocoder的类。我无法检查通过地理编码器输入的地址是否有效。当我添加一家公司/编辑一家公司时,这段代码非常有效,该公司的地址通过geocoder提供纬度和经度。但我需要代码来工作,这样当用户试图在编辑或创建公司时,将一个没有给出经度和纬度的地址放入时,就会弹出一个错误,并通知用户该地址无效 型号 class Company < ActiveRecord::Base validates :name, presence: true, length: { maxim
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
class公司(obj){obj.address.present?和obj.address_changed?}
保存后:设置弹出值
私有的
...
结束
查看
<% 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>
添加公司
'123测试街,城市州邮政编码''>
“30x5”%>
您可能需要对geocoder服务进行web/服务调用。你如何做到这一点取决于你想要什么:ajaxy请求或背景工作,等等
这是一个相当普遍的问题,因此,您可能会在programmers.stackexchange.com中获得更好的关注
但是,这里有一些链接可以帮助您:
谷歌地理编码API:
OpenStreetMap:因为您使用的是Geocoder,所以在保存之前,您只需要有机会检查Geocoder的结果。这一过程在it手册的“高级地理编码”一节中进行了解释。仅举一个例子,您可以这样做:
geocoded_by :address do |obj,results|
....
end
验证结果后,如果尚未获得坐标,则可以进行例外/添加验证错误/无论什么
当然,这意味着,你必须打电话给web服务,看看地址是否合适——就像其他人说的那样,在这之前进行一些基本的验证会很好。因此,经过几天的努力,我想出了一些解决方案。第一个是真正的黑客,但完成了我需要的。我的第二个解决方案更加优雅,从目前为止我所知道的情况来看,效果非常好!我希望其他人觉得这很有用 我只需几行代码就可以处理控制器中的所有逻辑
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
通过在我的地理编码之后创建另一个,我可以检查适当的值是否发生了变化,以及它们是否以某种方式发生了变化,而我知道地理编码中存在问题
如果地址改变了,但纬度没有改变,那么当地址通过地理编码器输入时,就不会得到返回的lat/long。如果是这种情况,那么我们只需添加一个错误,向用户抛出并返回false,这将停止对数据库的保存
我希望其他有这个问题的人都能找到这个帖子 肖恩·卡拉汉说的没问题。您可以通过以下方式改进代码:
def lat_changed?
if address_changed? && !latitude_changed?
self.errors.add(:address, "is not valid")
end
end
不必返回真/假您可以在如下示例中的模型中进行设置,以验证地址
地址更改时,地理编码
仅调用一次。
在geocoded\u by
方法中,我们显式设置为写入纬度
和经度
,以便在找不到地址时,这些列将设置为零
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
class公司
您是否要求SO为您编写地址验证代码?不,我只是不知道在哪里/如何检查地址是否有效。因此,基本上,当用户点击“添加公司”按钮时,如果用户输入了一个地址,而地理编码器无法从中获取lat/long,那么我需要提出一个错误。但我不知道如何做到这一点。您可以改进它:def lat\u changed?
`if address\u changed?&!latitude\u已更改?`self.errors.add(:address,“无效”)`end`end
我认为在验证回调后添加错误不是一个好主意。这是在假设如果地址发生更改,则必须更改latitude。这一定是真的吗?