使用Maps API计算两个地址的距离,然后将每个距离保存到数据库

问题描述 投票:0回答:2

我正在写一个应用程序,根据距离将孩子与幼儿园相匹配。

我正在尝试使用 Maps API 来计算多个地址之间的距离。 我想使用 open-uri

https://maps.googleapis.com/maps/api/distancematrix/json?origins=[address of child]&destinations=[adress of kindergarden]&key=XYZ

那将是对 api 的请求。

我的想法是在孩子创建过程之后发送请求。 我将从数据库中获取孩子地址和幼儿园地址并构建请求。
响应的距离将保存在每个孩子和幼儿园的关系表中 如何访问孩子和幼儿园的数据库条目? 然后保存到关系表中?

我当前的代码如下所示:

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

帮助将不胜感激?

ruby-on-rails google-maps-api-3 open-uri
2个回答
3
投票

这里的问题是您试图将 URL 作为字符串打开,因此它正在寻找一个以这种方式命名的文件,但它不存在。

这里有两个选择:

1。使用 HTTParty gem 发出 HTTP 请求

这是我最喜欢的方法。

将宝石包含在您的

Gemfile
中:

gem 'HTTParty'

在您的控制器中发出请求:

url = "https://maps.googleapis.com/maps/api/distancematrix/json?origins=" \
      "#{@child.adress}&destinations=#{@kiga.adress}&key=XYZ"
response = HTTParty.get(url)

现在如果你要打印出

response["rows"].first["elements"].first
的结果,你会看到这样的输出:

{"distance"=>{"text"=>"15.4 km", "value"=>15405}, "duration"=>{"text"=>"17 mins", "value"=>1001}, "status"=>"OK"}

如您所见,您有距离和持续时间信息。我猜你是在以米为单位的距离值之后:

relations.distance = response["rows"].first["elements"].first["distance"]["value"]

注意 1:我故意在单词地址(@child.adress、@kiga.adress)中重现了拼写错误,以便代码与您的设置一起使用,但请考虑将其修复为@child.address 和@kiga .地址.

注意 2:为简单起见,我没有对响应进行任何错误检查,这是您绝对应该注意的事情。

注意 3:请记住将 api 密钥更改为有效密钥,为了简单起见,我将其硬编码为 XYZ,就像您在问题中所做的那样。

2。使用 open-uri 将您的 url 解析为有效的 URI

您必须在控制器的开头要求库

'open-uri'
'JSON'

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

变量的内容

result
(解析后)如下所示:

{"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"}

无论您选择 HTTParty 方式还是 open-uri + JSON 解析方式,请务必检查响应状态代码。这两种方法都已在我的计算机上进行了本地测试,并取得了成功的结果。

希望对您有所帮助,干杯!


0
投票

另一种解决方案是查看此 Gem https://github.com/alexreisner/geocoder

如果你对你的儿童模型和你的 Kiga 模型进行地理编码,那么你可以很容易地获得一个到另一个的距离。

enter code here

这没有进行任何 API 调用,GEM 会为您完成此操作。

它也有一个非常方便的方法来返回位置附近的记录

@kiga.near(@child.coordinates, 10)

将返回所有带有 10km @child 坐标的 Kiga

© www.soinside.com 2019 - 2024. All rights reserved.