0
votes

I have a form that the user uses to enter a physical address, and I want to use the GeoCoder gem to convert that physical address to a lat/long value set that I can also store in the database when the model they form submission creates gets saved.

I'm having trouble deciding where I should put this call to use GeoCoder to populate the latitude and longitude values for the database. I thought it would go in the model class, but was not sure if I should do it in an initialize method where I accept the physical address and then inside the initialize method I use call to geocoder to set values for @latitude and @longitude, or is there a better way or place to do this such as simply using attr_accessor in the model and then calling it to set these values in the controller before the save action completes.

I guess my main confusion is due to in the controller in the new and create methods, there is not much there so could not figure out how to get this done upstream of the "save" that inserts the data for the resource into the database.

3
Why not read the readme before speculating? Geocoder is designed to do geocoding and reverse geocoding in the model. - max

3 Answers

1
votes

I'm having trouble deciding where I should put this call to use GeoCoder to populate the latitude and longitude values for the database.

Definitely in the model, this is something which you are doing in the backend and the user or view or controller has nothing to do with it..also, if I am not wrong, it makes an api call to another(probably google) server and such logics don't reside in controller.

Remember: Thin Controllers and Fat Models

How?

You can probably use a before_create callback like

before_create :assign_lat_long

private

def assign_lat_long
  # the logic
end

If you don't need a quick/on the go lookup for the lat-longs, I would suggest you to do it asynchronously like delayed_job or some other similar service which you already use. Basically, it won't affect the UX or response time of your server as it is now independent of 3rd party API's response..

1
votes

Fat models, skinny controllers, and a whole bunch of service objects.

But for the sake of "just getting it done", model works fine.

The idea being is that you should be able to call the same method (in this case, your Geocoding method) anywhere without having to copy-pasta code. You know, that whole don't-repeat-yourself thing.

In your (example) place.rb

before_save :if => { |_| self.address_changed? && self.address.present? } do 
  result = Geocoder.search(self.address)
  self.lat, self.lng = result.lat, result.lng
end
1
votes

i am a bit confused about what are you looking for.I have been using Geocoder for quite a long time and this is what it does...including what you are looking for -

  • you need to add the geocoder gem and then tell the gem which model will hold the address....in your case it can be address.rb with address column assuming other columns too - latitude,longitude,city,country...etc.
  • The above will be achieved by using geocoded_by in your address.rb for that column which will help geocoder to populate the other columns.
  • You dont have to worry about where should it be placed because logically, its always in the model and initialized on save.
  • So all you have to do is..in your create action in controller...when you do @address.save..this will trigger geocoder to fetch all the values from the params[:address] field coming from the form that you have submitted.

Once the address object is saved, other values will too get populated and then you can use them the way you want.

Hope this helps.