0

In JavaScript, I can easily get my current Latitude and Longitude Coordinates and I'm trying to implement this in Ruby On Rails

In Javascript, I can use the following code to get my current Latitude and Longitude.

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;
}

In Rails, I am able to get my current IP address using the following

Net::HTTP.get(URI.parse('http://checkip.amazonaws.com/')).squish

However, I am unable to convert this to a latitude and longitude,

The Javascript approach asks the users permission to use their current location which would be ideal for the scenario I am facing. I realise that there are gems out there that tackle this problem however I need this to work on localhost which the javascript method does.

4

2 回答 2

2

geocoder gem will not work with localhost. And if to use it in production it can only give approximate results.

More precise result can be received by sending ajax request from frontend to backend.

Example: enter image description here

<!-- 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'
于 2019-07-13T02:33:18.747 回答
1

you can use geocoder gem

first open your Gemfiles and add this line

gem 'geocoder'

from terminal run bundle install to install gem files then run rails console to test it here is sample to search for latitude and longitude for 10 downing street, london

results = Geocoder.search("10 Downing Street, london")
latitude = results.first.coordinates[0]
longitude = results.first.coordinates[1]
于 2019-07-13T01:24:50.050 回答