#ruby #ruby-on-rails-5
#ruby #ruby-on-rails-5
Вопрос:
Мне нужно вернуть расстояния между двумя точками с помощью функции haversine. Я извлекаю массив кординат из базы данных, используя область видимости. Но у меня возникают проблемы с циклическим перебором массива для возврата расстояний между каждой созданной парой.
В show() я хочу, чтобы просматриваемый адрес был базовой / исходной точкой, затем он должен проходить через базу данных для сопряжения со всеми другими точками адреса, чтобы вернуть их расстояния на основе @origin .
В настоящее время я возвращаю только одно значение. Мне действительно нужна помощь.
Ниже приведен мой код
class AddressesController < ApplicationController
before_action :set_address, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
# GET /addresses
# GET /addresses.json
def index
@addresses = Address.all
end
def haversine_distance(geo_a, geo_b, miles=false)
# Get latitude and longitude
lat1, lon1 = geo_a
lat2, lon2 = geo_b
# Calculate radial arcs for latitude and longitude
dLat = (lat2 - lat1) * Math::PI / 180
dLon = (lon2 - lon1) * Math::PI / 180
a = Math.sin(dLat / 2) *
Math.sin(dLat / 2)
Math.cos(lat1 * Math::PI / 180) *
Math.cos(lat2 * Math::PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2)
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
d = 6371 * 1000 * c # in meters
end
# GET /addresses/1
# GET /addresses/1.json
def show()
@origin = [@address.latitude, @address.longitude]
@destination = Address.get_lat_lon_array
@destination.each do |dest|
@distance = haversine_distance(@origin, dest).to_i
end
end
# GET /addresses/new
def new
@address = Address.new
end
# GET /addresses/1/edit
def edit
end
# POST /addresses
# POST /addresses.json
def create
@address = Address.new(address_params)
@address.user_id = current_user.id
respond_to do |format|
if @address.save
format.html { redirect_to dashboard_path, notice: 'Address was successfully created.' }
format.json { render :show, status: :created, location: @address }
else
format.html { render :new }
format.json { render json: @address.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /addresses/1
# PATCH/PUT /addresses/1.json
def update
respond_to do |format|
if @address.update(address_params)
format.html { redirect_to my_address_path, notice: 'Address was successfully updated.' }
format.json { render :show, status: :ok, location: @address }
else
format.html { render :edit }
format.json { render json: @address.errors, status: :unprocessable_entity }
end
end
end
# DELETE /addresses/1
# DELETE /addresses/1.json
def destroy
@address.destroy
respond_to do |format|
format.html { redirect_to addresses_url, notice: 'Address was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_address
@address = Address.find(params[:id])
end
# Only allow a list of trusted parameters through.
def address_params
params.require(:address).permit(:landmark, :longitude, :latitude)
end
end
<%= render "layouts/main-nav" %>
<div class="container py-5 dash-view">
<div class="row" id="dash">
<%= render "layouts/left" %>
<div class="col-md-8">
<p><%= @address.landmark %></p>
<p><%= @distance %> meters</p>
</div>
</div>
</div>
</div>
class Address < ApplicationRecord
validates :latitude, :longitude, :landmark, presence: true
belongs_to :user
scope :get_lat_lon_array, -> { pluck(:latitude, :longitude) }
end
Я хочу, чтобы мой вывод представлял собой таблицу в представлении отображения расстояний других адресов по отношению / от к адресу текущего пользователя
Комментарии:
1. Можете ли вы опубликовать выборку массива (небольшую выборку) и ожидаемый результат?
2. Я извлекаю массив из адресной таблицы, используя это. область действия:get_lat_lon_array, -> { pluck(:широта, :долгота) }
3. Можете ли вы использовать это? Спасибо [[0.384687e0, 0.32658527e2], [0.393035e0, 0.3264051e2], [0.323493e0, 0.32647846e2], [0.364948e0, 0.32637298e2], [0.309571e0, 0.32652247e2], [0.386782e0, 0.32652977e2]]
4. Я думаю, это потому, что вы переназначаете переменную экземпляра @distance на каждой итерации цикла. Вместо использования каждого, используйте метод map для цикла. Также удалите назначение внутри блока цикла.
5. Не могли бы вы показать мне, как это сделать? потому что, когда я пытаюсь, я все равно получаю тот же результат. Спасибо
Ответ №1:
Если я понимаю вашу проблему, вам нужен массив #map, который будет использоваться таким образом:
@destination = [[0.384687e0, 0.32658527e2], [0.393035e0, 0.3264051e2], [0.323493e0, 0.32647846e2], [0.364948e0, 0.32637298e2], [0.309571e0, 0.32652247e2], [0.386782e0, 0.32652977e2]]
origin = [0.384687e0, 0.32658527e2]
@distances = @destination.map { |point| haversine_distance(point, origin).to_i }
@distances #=> [0, 2208, 6907, 3223, 8382, 660]
Пример и ссылка на документ должны вам помочь.