简体   繁体   English

Rails中的Ruby Geocoder gem问题

[英]Problems with Ruby Geocoder gem in Rails

I have a model, Offers, and am trying to obtain the ip address from the user and geocode the coordinates by latitude and longitude. 我有一个“报价”模型,正在尝试从用户那里获取IP地址,并按纬度和经度对坐标进行地理编码。 The gem documentation indicates that where the ip address is known the code should be: gem文档指出,在已知IP地址的地方,代码应为:

Model: 模型:

      geocoded_by :ip_address, :latitude => :latitude, :longitude => :longitude

However I don't have the ip address saved initially so I changed it to this: 但是我最初没有保存IP地址,所以我将其更改为:

if :current_location
self.ip_address = request.ip
          geocoded_by :ip_address, :latitude => :latitude, :longitude => :longitude
end

request.ip is a method from ActionView I believe so can't be called from the Model. request.ip是ActionView中的方法,我相信不能从Model中调用它。 I have tested this as a helper method and it returns the local:host address. 我已经将此作为辅助方法进行了测试,并且它返回了local:host地址。 But when I try and save it in this format it is not saving anything to the model. 但是,当我尝试以这种格式保存它时,并没有将任何内容保存到模型中。

What is the neatest way to save the ip_address to the model so it can be used in this format? 将ip_address保存到模型以便可以以这种格式使用的最巧妙的方法是什么? Should it be extracted to a helper method? 是否应该将其提取为辅助方法? Is there a way to include or require the right module in the model? 有没有办法在模型中includerequire正确的模块?

For reference the gem guide is here: http://www.rubygeocoder.com 供参考的宝石指南在这里: http : //www.rubygeocoder.com

All help appreciated, thanks. 感谢所有帮助,谢谢。

You may want to use the Geocoder class directly instead of using the geocoded_by method in the model. 您可能要直接使用Geocoder类,而不是在模型中使用geocoded_by方法。 I would create a service object that handles the creation of Offers. 我将创建一个处理要约创建的服务对象。 You can find the coordinates of an ip_address by doing the following: 您可以通过执行以下操作找到ip_address的坐标:

Geocoder.coordinates(ip_address) # => [latitude, longitude]

I would do something like the following: 我将执行以下操作:

class OfferGeocoder
  attr_reader :request, :params, :coordinates

  def initialize options = {}
    @request = options[:request]
    @params = options[:params]
  end

  def coordinates
    @coordinates ||= Geocoder.coordinates(request.remote_ip)
  end

  def create_offer
     Offer.new(params.merge({
       latitude: coordinates.first,
       longitude: coordinates.last
     })
  end
end

In your create action of your controller you can call: 在控制器的创建动作中,您可以调用:

def create
   @offer = OfferGeocoder.new(params: offer_params, request: request).create_offer
   if @offer.save
     ...
end

OK so since the method request.ip doesn't work within the model the easiest way is through the controller: 好的,因为方法request.ip在模型中不起作用,所以最简单的方法是通过控制器:

class OffersController<ApplicationController

 def create
    @offer = Offer.new(offer_params)
    if @offer.current_location
    @offer.ip_address = request.ip

...
  end
end

Additionally the request.ip method does not work in development mode as it returns the local host address and not a true ip address. 另外,request.ip方法在开发模式下不起作用,因为它返回本地主机地址而不是真实的IP地址。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM