Вы можете передать IP-адрес пользователя в API, который сопоставляет IP-адреса с определенным местоположением.
Один из способов сделать это - создать модуль ruby в lib, который имеет метод, который принимает IP-адрес и отправляет запрос в API для получения местоположения.
module Location
require 'net/http'
require 'json'
def get_location ip_address
location = Net::HTTP.get(URI("https://ipapi.co/#{ip_address}/json/"))
JSON.parse(location)
end
module_function :get_location
end
Возвращаемый JSON включает долготу и широту.
Затем вы можете вызвать этот метод с вашего контроллера пользователя
require 'location'
class UsersController < ApplicationController
def create
@user = User.new(params.require(:user).permit(:longitude, :latitude))
location = get_user_location
@user.longitude = location["longitude"]
@user.latitude = location["latitude"]
if @user.save
# Do something
else
# Do somehting else
end
end
private
def get_user_location
ip_address = request.remote_ip
Location.get_location ip_address
end
end
Примечание: ip_address не будет работать локально, поэтому для его проверки вам придется жестко кодировать по ip-адресу вместо вызова request.remote_ip (то есть ip_address = "8.8.8.8").
EDIT:
Обновление местоположения пользователей потребовало бы в основном той же логики, что и настройка во время действия создания. Итак, я бы порекомендовал просто извлечь всю логику в модуль ... что-то вроде этого
module Location
require 'net/http'
require 'json'
def get_location ip_address
location = Net::HTTP.get(URI("https://ipapi.co/#{ip_address}/json/"))
JSON.parse(location)
end
def set_location user ip_address
location = get_location ip_address
user.longitude = location["longitude"]
user.latitude = location["latitude"]
user.save
end
module_function :set_location
end
Это позволит вам избавиться от всей логики расположения в контроллере пользователей, а затем повторно использовать метод set_location на всех ваших контроллерах.