Rails сортирует дочернюю модель на основе расчета расстояния до родительской модели

У меня есть модель product и модель shop. Отношения между двумя магазин has_many продукты и продукты belongs_to магазин.

Модель магазина имеет два поля longitude и latitude, используемые для расчета расстояния с помощью geokit-rails. Мне удалось отсортировать магазины по ближайшему расстоянию до любой заданной долготы и широты, используя:

Shop.by_distance(origin:[params[:latitude], params[:longitude]]).sort_by{|s| s.distance_to([params[:latitude], params[:longitude]])}

Проблема в продуктах. Продукты также должны быть отсортированы по месту нахождения ближайшего магазина. Я просмотрел и обнаружил, что дочерняя модель может быть отсортирована по родительским атрибутам следующим образом:

Product.joins(:shop).order('shops.name')

Функция заказа работает, только если указано поле модели. Как я могу сортировать товары, рассчитывая расстояние до магазина.

Пожалуйста помоги.


person Sushil    schedule 28.03.2017    source источник
comment
.by_distance уже применит предложение порядка и отсортирует записи по расстоянию от источника. Использование .sort_by, которое перебирает результаты в виде массива, ничего не дает - вы буквально делаете одно и то же дважды.   -  person max    schedule 28.03.2017
comment
Спасибо, что узнали. Я починю это.   -  person Sushil    schedule 28.03.2017


Ответы (2)


Посмотрите документацию по использованию :through — это должно быть именно то, что вы необходимость.

Итак, Product будет выглядеть так:

class Product < ActiveRecord::Base
  belongs_to :shop
  acts_as_mappable through: :shop
  ...
end

И ваш запрос будет примерно таким:

Product.joins(:shop).by_distance(origin: [params[:latitude], params[:longitude]])
person gwcodes    schedule 04.04.2017

Если вы уже можете фильтровать и сортировать Магазин

@shops = Shop.by_distance(origin:[params[:latitude], params[:longitude]]).sort_by{|s| s.distance_to([params[:latitude], params[:longitude]])}

Это позволит получить все товары из каждого магазина в зависимости от расстояния:

@closest_products = @shops.map(&:products)

Если вы хотите отсеять дубликаты товаров, используйте вместо этого:

@closest_products = @shops.map(&:children).flatten.uniq

Вы можете попробовать альтернативный метод (я не проверял это):

@closest_products = Product.where(shop: @shops)
person Galih Muhammad    schedule 28.03.2017
comment
Цель здесь состоит в том, чтобы сначала получить продукты, которые могут быть отфильтрованы, а затем отсортированы по их магазинам. Попытка второй строки привела к следующему: #‹NoMethodError: неопределенный метод `ассоциации' для #‹ActiveModel::Serializer::CollectionSerializer:0x007f9347f0f398›› - person Sushil; 28.03.2017