简体   繁体   中英

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. The gem documentation indicates that where the ip address is known the code should be:

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:

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. I have tested this as a helper method and it returns the local:host address. 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? Should it be extracted to a helper method? Is there a way to include or require the right module in the model?

For reference the gem guide is here: 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. 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:

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:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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