Unfortunately geocoder does only support ActiveRecord and MongoDB as storage backends but not JSON. With ActiveRecord / Mongo geocoder can also leverage the query language of the database (e.g. SQL) to efficiently find locations near a point. In your case you have now basically two options:
Store JSON data in ActiveRecord
You could store your JSON data in a database and use ActiveRecord to query the data. There is already a good documentation for this on the gem official GitHub page here https://github.com/alexreisner/geocoder#geospatial-database-queries.
Create ActiveRecord like object
If you don't need to store the data from your API request I would recommend to use an Active Record like volatile data storage.
class Location
attr_reader :id, :name, :lat, :long
def initialize(id:, name:, lat:, long:)
@id = id
@name = name
@lat = lat
@long = long
end
def to_coordinates
[lat.to_f, long.to_f]
end
class << self
attr_accessor :locations
def from_json(json)
json.each do |location|
locations << new(
id: location[:location_id],
name: location[:name],
lat: location[:lat],
long: location[:long]
)
end
end
def all
locations
end
end
self.locations = []
end
json = [
{"location_id": 1, "name": "location1", "lat": "22.21", "long": "-72.54" },
{"location_id": 2, "name": "location2", "lat": "45.21", "long": "-74.21" }
]
Location.from_json(json)
puts Location.all
We now 'import' your API JSON response and store it in an array as a class attribute in Location. This also has the advantage that you work with objects and not with hashes / JSON anymore.
Now we can create a near class method to select all locations close to one point.
def near(lat, long, radius: 20, units: :km)
all.select do |location|
Geocoder::Calculations.distance_between(location, [lat, long], units: units) < radius
end
end
The disadvantage here is that we need to iterate over all locations and calculate the distance as we don't have a query language for the JSON data. If performance is an issue, I would suggest to use an SQL database (see previous suggestion).
Full example
require "geocoder"
class Location
attr_reader :id, :name, :lat, :long
def initialize(id:, name:, lat:, long:)
@id = id
@name = name
@lat = lat
@long = long
end
def to_coordinates
[lat.to_f, long.to_f]
end
class << self
attr_accessor :locations
def from_json(json)
json.each do |location|
locations << new(
id: location[:location_id],
name: location[:name],
lat: location[:lat],
long: location[:long]
)
end
end
def all
locations
end
def near(lat, long, radius: 20, units: :km)
all.select do |location|
Geocoder::Calculations.distance_between(location, [lat, long], units: units) < radius
end
end
end
self.locations = []
end
json = [
{"location_id": 1, "name": "location1", "lat": "22.21", "long": "-72.54" },
{"location_id": 2, "name": "location2", "lat": "45.21", "long": "-74.21" }
]
Location.from_json(json)
puts Location.near(45.21, -74.21)