2

I have a model named Location that uses Geocoder to retrieve the address from the coordinates when it is created. Then I have an Android app that asks the controller for the list of locations around a particular point in the index method of my locations_controller :

def index
    @locations = Location.near([params[:latitude], params[:longitude]], params[:search_radius], :order => :distance)
end

And the result is formatted in json with Rabl and sent to the app :

child :data do
  child @location do
    attributes :id, :name, :address, :city, :state, :zipcode, :country_name, :latitude, :longitude, :distance
  end
end

It works well so far, and :distance is calculated automatically.

But now I give the possibility for the user to create a Location in the app, so I designed the create method this way :

def create
  @location = Location.new(params[:location])
  if @location.save
    @location
  else
    render :status => :unprocessable_entity,
           :json => { :success => false,
                      :info => @location.errors,
                      :data => {} }
  end
end

The creation works great, I can send the rabl file containing basic information to the user but my problem is that :distance is not calculated.

I wanted to use the same Rabl template that for the index method and add something like this but it does not work :

node(:distance) { |location| location.distance_to(params[:latitude], params[:longitude]) }

Can I use params in the Rabl file to calculate it ?

Or do I have to do it in the controller ? Do I need to add an attribute in my model ?

UPDATE

Here is my Location model :

class Location < ActiveRecord::Base

    attr_accessible :address, :city, :state, :zipcode, :country_name, :latitude, :longitude, :name

    reverse_geocoded_by :latitude, :longitude do |obj,results|
      if geo = results.first
          obj.address = geo.street_address
          obj.city = geo.city
          obj.state = geo.state_code
          obj.zipcode = geo.postal_code
          obj.country_name = geo.country
      end
   end
   after_validation :reverse_geocode
end
jbihan
  • 3,053
  • 2
  • 24
  • 34
  • Is the distance calculated properly when the location is created and you make an additional request for it there after? – rudolph9 Sep 01 '13 at 19:13
  • Well I didn't try that because I wanted to avoid my Android app to do two requests in a row to the server, but I'd say that once in the database Geocoder will find it yes. I will try. Thanks ! – jbihan Sep 01 '13 at 19:16
  • How about instead of returning `@location` upon successful `@location.save` you redirect to `index`? – rudolph9 Sep 01 '13 at 22:38
  • I see what you mean, but I can have a big list of locations, I'm not it's worth sending this list back. But I will try that too, thanks. I just thought there would be an easy way to do this in the same request, but maybe not! – jbihan Sep 02 '13 at 00:09
  • As a low barriers approach, that is my first thought of how to fix this issues. As far as fixing the object returned by `Location.new`, it all depends on how you are computing `@location.distance` my bet is you simply have a hook that isn't firing at the right time. Could you post your `Location` model? – rudolph9 Sep 02 '13 at 12:32
  • I've updated my post with the `Location` model, but it's not complex. I don't know if you know Geocoder, but my model does not include a `:distance` attribute, it is calculated automatically by Geocoder. I guess I will have to implement one of the solutions we talked about, adding a `distance` attribute, render all the `locations` or create a new web service that renders the distance for a location – jbihan Sep 02 '13 at 17:05

1 Answers1

2

In fact it was simpler that I expected, I post the solution I found if other people wonder how to do it.

In the create method of locations_controller, I created an instance variable to store the result of distance_to :

@distance_to = @location.distance_to([params[:current_latitude],params[:current_longitude]])

Then in create.json.rabl I created a node to display this instance variable :

node (:distance_to) { @distance_to }

I really thought it would be a lot more difficult than that... Thanks @rudolph9 for your help!

jbihan
  • 3,053
  • 2
  • 24
  • 34