在 Rails 上获取 Ruby 的纬度和经度

Get Latitude and Longitude in Ruby On Rails

在 JavaScript 中,我可以轻松获得当前的经纬度坐标,我正尝试在 Ruby 中实现此功能 Rails

在Javascript中,我可以使用下面的代码获取我当前的纬度和经度。

var x = document.getElementById("demo");

    function getLocation() {
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showPosition);
  } else { 
    x.innerHTML = "Geolocation is not supported by this browser.";
  }
}

function showPosition(position) {
  x.innerHTML = "Latitude: " + position.coords.latitude + 
  "<br>Longitude: " + position.coords.longitude;
}

在 Rails 中,我可以使用以下

获取我当前的 IP 地址
Net::HTTP.get(URI.parse('http://checkip.amazonaws.com/')).squish

但是,我无法将其转换为纬度和经度,

Javascript 方法要求用户允许使用他们当前的位置,这对于我面临的场景来说是理想的。我意识到那里有解决这个问题的宝石但是我需要它在 javascript 方法所做的本地主机上工作。

您可以使用地理编码器gem

首先打开你的 Gemfiles 并添加这一行

gem 'geocoder'

从终端 运行 捆绑安装以安装 gem 文件 然后 运行 rails 在此处测试的控制台是搜索伦敦唐宁街 10 号纬度和经度的示例

results = Geocoder.search("10 Downing Street, london")
latitude = results.first.coordinates[0]
longitude = results.first.coordinates[1]

geocoder gem 不适用于本地主机。如果在生产中使用它,它只能给出 近似 个结果。

通过从前端向后端发送 ajax 请求,可以获得更精确的结果。

示例:

<!-- application.html.erb -->
<!DOCTYPE html>
<html>
  <head>
    <%= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js' %>
    <%= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.0/noty.js' %>
    <%= stylesheet_link_tag 'https://cdnjs.cloudflare.com/ajax/libs/noty/3.1.0/noty.min.css' %>

    <script>
      // It's bad to write inline javascript. To be moved into separate .js file
      $(function() {
        Noty.overrideDefaults({ theme: 'relax', layout: 'topCenter' });

        $('.getLocation').click(function(e) {
          event.preventDefault();

          if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(position) {
              $('.latInput').val(position.coords.latitude);
              $('.longInput').val(position.coords.longitude);

              new Noty({
                text: "Got location",
                type: "success"
              }).show();
            }, function(position) {
              new Noty({
                text: "Could not get location",
                type: "error"
              }).show();
            });
          } else {
            new Noty({
              text: "Geolocation is not supported by this browser.",
              type: "error"
            }).show();
          }
        });

        $('.resetLocation').click(function(e) {
          event.preventDefault();

          $('.latInput').val('');
          $('.longInput').val('');
        });

        $('.submitAjax').click(function(e) {
          event.preventDefault();

          var lat = $('.latInput').val();
          var long = $('.longInput').val();
          if (lat && long) {
            $.ajax({
              url: "/",
              data: {
                lat: lat,
                long: long
              }
            }).done(function() {
              new Noty({
                text: "Data was successfully submitted to server via AJAX",
                type: "success"
              }).show();
            }).fail(function() {
              new Noty({
                text: "Couldn't send data",
                type: "error"
              }).show();
            });
          } else {
            new Noty({
              text: "Click on 'Get Location' button first",
              type: "error"
            }).show();
          }
        });

        $('.clearAndSubmit').click(function(e) {
          $('.latInput').val('');
          $('.longInput').val('');
        });
      });
    </script>
  </head>
  <body>
    <%
      ip = request.remote_ip
      ip = '8.8.8.8' if ip.in?(["::1", "127.0.0.1"])
    %>
    Geocoder.search(ip):
    <br />
    <textarea cols="50" rows="10"><%= Geocoder.search(ip) %></textarea>
    <hr />
    <% if params[:lat].present? && params[:long].present? %>
      Form was submitted:
      <br />
      Lat: <%= params[:lat] %>
      <br />
      Long: <%= params[:lat] %>
    <% else %>
      Form was not submitted
    <% end %>
    <br />
    <br />
    <%= form_tag '/', method: :get do |f| %>
      <button class="getLocation">Get Location</button>
      &nbsp;
      <button class="resetLocation">Reset Location</button>
      <br />
      <br />
      <%= label_tag :lat, 'Lat:' %>
      <%= text_field_tag :lat, params[:lat], class: 'latInput' %>      
      <%= label_tag :long, 'Long:' %>
      <%= text_field_tag :long, params[:long], class: 'longInput' %>      
      <br />
      <br />
      <button class="submitAjax">Submit location to server via ajax</button>      
      <br />
      <br />
      <%= submit_tag "Submit location to server via form submit" %>
      <br />
      <br />
      <button class="clearAndSubmit">Clear form and submit</button>      
    <% end %>
  </body>
</html>
# application_controller.rb
class ApplicationController < ActionController::Base
  before_action do
    # Implemented before_action for demonstration purposes. Should be moved into action.

    if params[:lat].present? && params[:long].present?
      Rails.logger.info(['Received lat&long from AJAX request', {lat: params[:lat], long: params[:long]}])
      # current_user.lat = params[:lat]
      # current_user.lat = params[:lng]
      # current_user.save!
    end
  end
end
# gemfile.rb
#...
gem 'geocoder'