ruby-on-railsrubyrails-geocoder

How to create a select options in the form from a geocoded list?


This is my first time geocoding anything. I've tried so many different options I've lost track of what I've tried. I have a gym.rb model that lists all the gyms in a state. I'm using rails geocoder gem to search from a user's address to get all the gyms within 10 miles of the user's address. Then I want to take just the names of those gyms within 10 miles and put them in a form f.select :gym1. I can't figure out how to do this. Using Rails 7.

Gym model:

  class Gym < ApplicationRecord

  geocoded_by :address
  after_validation :geocode

  def address
    [street, city, state, zip].compact.join(", ")
  end

  def address_changed?
    street_changed? || city_changed? || zip_changed? || state_changed?
  end
end

In the rails console I run:

@gyms = Gym.near(["current_user.latitude, current_user.longitude"], 10)

and I get back a list of gyms with: id: name: address:

In the Geocoder docs: Geocoder::Result object, result

I'm not sure how to pull out just the gym names here and put them in the select array. To get access to each gym name you have to write "result.first.name", then for the second name its "result.second.name"

And once I have that list do I assign it to an @instance variable like: @local_gym_list = [result.first.name, result.second.name, ...]

Then I tried using a static @local_gym_list and did in form:

<%= f.select :gym1, [@local_gym_list] %>

but that's not working.So could someone help show me how to put the geocode search names into an @local_gym_list and then make that the selector in the form?


Solution

  • You're passing the string "current_user.latitude, current_user.longitude" and not the coordinates to the method.

    Start by fixing the bug:

    @gyms = Gym.near([current_user.latitude, current_user.longitude], 10)
    

    Then refactor:

    class User
      # ...
      def coordinates
        [latitude, longitude]
      end 
    end
    
    @gyms = Gym.near(current_user.coordinates, 10)
    

    Creating the select here is no different than with any other collection of records.

    Just use the collection helpers provided by rails and pass it the name of the input you want to create, the collection, the value method and the label method.

    <%= f.collection_select(:gym_id, @gyms, :id, :name) %>
    

    And once I have that list do I assign it to an @instance variable like: @local_gym_list = [result.first.name, result.second.name, ...]

    You never need to manually assign one thing after another to an array in Ruby. If you ever find yourself being a human compiler stop and rethink.

    If you did have to create an array of names (which you don't) you could simply do .map(&:name) or use .pluck(:id, :name) to get the two attributes you need.