Can I have reverse_geocoded_by and geocoded_by at the same time in a model? Rails

Hugo Source

I'm looking to allow my model to be geocoded by full_street_address and reverse_geocoded_by :latitude and :longitude so that I can call Address.near and get them either by one or the other way.

This seems to work but could this approach cause potential issue or is it correct?

Here's my code:

class Address < ApplicationRecord
  geocoded_by :full_street_address
  after_validation :geocode
  reverse_geocoded_by :latitude, :longitude

  def full_street_address
    self.street + self.city + self.country
  end
end
ruby-on-railsrubygeocoder

Answers

answered 3 months ago Roma149 #1

It works but it's redundant. That's because with geocoded_by you have the full street address and obtain the latitude and longitude, which is your case. But reverse_geocoded_by allows you to obtain an address from a latitude and longitude, but you already have it.

Just remove the reverse_geocoded_by and if you want to use the latitude and longitude simply call the fields in your database: self.latitude and self.longitude, for example, which you should have defined (and the geocoding service is filling out for you).

answered 3 months ago 7urkm3n #2

Yes, You can use it, by default it will overwrite if giving address and lat/lng addresses.

You can split into two classes and call Address.near([:lat, :lng]) too later after save.

Models

- /model/address.rb
   class Address < ApplicationRecord
      #any association/validations here

      geocoded_by :full_street_address

      #by default it will save full address to address field. 
      reverse_geocoded_by :latitude, :longitude do |obj,results|
        if geo = results.first
            #customize as you want
              obj.street  = geo.address.split(',')[0]
              obj.city    = geo.city
              obj.zip     = geo.postal_code
              obj.state   = geo.state
        end
      end

      def full_street_address
         self.street + self.city + self.country
      end
   end

- /model/address/with_address.rb
   class Address::WithAddress < Address
      after_validation :geocode
   end

- /model/address/with_lat_lng.rb
   class Address::WithLatLng < Address
     after_validation :reverse_geocode
   end

Controller

   address = Address::WithLatLng.create(latitude: 40.5236803, longitude: -80.2249546)
   # returns: will save lat/lng and address/city/state/zip fields saved from api
   address.full_street_address
   #or
   address = Address::WithAddress.create(address: "601 fake st.", city: "brooklyn", state: "ny", zip: "11220")
   # returns: will save address and latitude:, longitude: will fetch from api.
   address.full_street_address

comments powered by Disqus