I'm writing an app which matches children to kindergartens based on the distance.
I am trying to use the Maps API to calculate distances between multiple addresses. I want to use open-uri
https://maps.googleapis.com/maps/api/distancematrix/json?origins=[address of child]&destinations=[adress of kindergarden]&key=XYZ
that would be the request for the api.
My idea was to send the request after the creation process of the child.
I would take the child address and the kindergarten address from the database and build the request.
The responded distance would be saved in a relations table for each child and kindergarten
How can I access the database entries of the child and the kindergartens?
And then save it to the relations table?
My current code looks as follows:
def create
@child = Child.new child_params
@child.user = current_user
@child.save
origin = @child.adress
destination = @kiga.adress
response = open('https://maps.googleapis.com/maps/api/distancematrix/json?origins=' + [address of child] + '&destinations=' + [adress of kindergarden] + '&key=XYZ').read
relations.distance = response.rows.elements[0]
respond_to do |format|
if @child.save
format.html { redirect_to @child, notice: 'Child was successfully created.' }
format.json { render :show, status: :created, location: @child }
else
format.html { render :new }
format.json { render json: @child.errors, status: :unprocessable_entity }
end
end
Help would be appreciated?
The issue here is that you are trying to open the URL as a string, so it's looking for a file named that way and it does not exist.
You have two options here:
This one is my favourite approach.
Include the gem in your Gemfile
:
gem 'HTTParty'
Make the request within your controller:
url = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=" \
"#{@child.adress}&destinations=#{@kiga.adress}&key=XYZ"
response = HTTParty.get(url)
Now if you were to print out the result of response["rows"].first["elements"].first
you would see an output like this:
{"distance"=>{"text"=>"15.4 km", "value"=>15405}, "duration"=>{"text"=>"17 mins", "value"=>1001}, "status"=>"OK"}
As you can see you have distance as well as duration information. I am guessing you are after the distance value in meters so:
relations.distance = response["rows"].first["elements"].first["distance"]["value"]
NOTE 1: I intentionally reproduced the typo in the word address (@child.adress, @kiga.adress) so that the code works with your setup, but give a thought to fixing it to @child.address and @kiga.address.
NOTE 2: For simplicity I did not do any error checking on the response, that's something you should definitely take care of.
NOTE 3: Remember to change the api key to a valid one, I hardcoded it for simplicity to XYZ like you did in your question.
You have to require the libraries 'open-uri'
and 'JSON'
in the beginning of the controller:
require 'open-uri'
require 'JSON'
def create
@child = Child.new child_params
@child.user = current_user
@child.save
origin = @child.adress
destination = @kiga.adress
# Parse the string url into a valid URI
url = URI.parse(
"https://maps.googleapis.com/maps/api/distancematrix/json?origins=" \
"#{@child.adress}&destinations=#{@kiga.adress}&key=XYZ"
)
# Open the URI just like you were doing
response = open(url).read
# Parse the string response in JSON format
result = JSON.parse(response)
# Extract the distance value in meters
relations.distance = result["rows"].first["elements"].first["distance"]["value"]
respond_to do |format|
if @child.save
format.html { redirect_to @child, notice: 'Child was successfully created.' }
format.json { render :show, status: :created, location: @child }
else
format.html { render :new }
format.json { render json: @child.errors, status: :unprocessable_entity }
end
end
The contents of the variable result
(after parsing it) look like the following:
{"destination_addresses"=>["Destination address"], "origin_addresses"=>["Origin address"], "rows"=>[{"elements"=>[{"distance"=>{"text"=>"15.4 km", "value"=>15405}, "duration"=>{"text"=>"17 mins", "value"=>1001}, "status"=>"OK"}]}], "status"=>"OK"}
Either if you go for the HTTParty way or the open-uri + JSON parsing way, make sure you check the response status codes. Both approaches have been tested locally on my computer with successful results.
I hope it helps, cheers!