Мне интересно, как лучше всего отображать уникальные записи из has_many через отношения в Rails3.
У меня три модели:
class User < ActiveRecord::Base
has_many :orders
has_many :products, :through => :orders
end
class Products < ActiveRecord::Base
has_many :orders
has_many :users, :through => :orders
end
class Order < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :product, :counter_cache => true
end
Допустим, я хочу перечислить все продукты, заказанные клиентом, на их странице выставки.
Возможно, они заказывали некоторые продукты несколько раз, поэтому я использую counter_cache для отображения в порядке убывания ранжирования в зависимости от количества заказов.
Но если они заказывали продукт несколько раз, мне нужно убедиться, что каждый продукт указан только один раз.
@products = @user.products.ranked(:limit => 10).uniq!
работает, когда для продукта имеется несколько записей о заказах, но генерирует ошибку, если продукт был заказан только один раз. (ранжированный - это настраиваемая функция сортировки, определенная в другом месте)
Другая альтернатива:
@products = @user.products.ranked(:limit => 10, :select => "DISTINCT(ID)")
Я не уверен, что придерживаюсь правильного подхода.
Кто-нибудь еще занимался этим? С какими проблемами вы столкнулись? Где я могу узнать больше о разнице между .unique! и DISTINCT ()?
Как лучше всего создать список уникальных записей через has_many, через отношения?
Спасибо
источник
has_many :products, :through => :orders, :uniq => true
не рекомендуется. Вместо этого вы должны сейчас написатьhas_many :products, -> { uniq }, through: :orders
.DISTINCT
иORDER BY
положения, вы всегда можете использоватьhas_many :products, -> { unscope(:order).distinct }, through: :orders
has_many :subscribed_locations, -> { unscope(:order).select("DISTINCT ON (locations.id) locations.*") },through: :people_publication_subscription_locations, class_name: 'Location', source: :location
иначе вы получитеrails ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR: could not identify an equality operator for type json
Обратите внимание, что
uniq: true
было удалено из допустимых вариантов дляhas_many
Rails 4.В Rails 4 вы должны предоставить область видимости для настройки такого поведения. Области видимости могут быть предоставлены через лямбды, например:
В руководстве по рельсам рассказывается об этом и других способах использования областей видимости для фильтрации запросов ваших отношений, прокрутите вниз до раздела 4.3.3:
http://guides.rubyonrails.org/association_basics.html#has-many-association-reference
источник
undefined method 'except' for #<Array...
и это было потому, что я использовал.uniq
вместо.distinct
Вы могли бы использовать
group_by
. Например, у меня есть корзина для покупок в фотогалерее, для которой я хочу, чтобы элементы заказа были отсортированы по фотографиям (каждую фотографию можно заказывать несколько раз и в распечатках разного размера). Затем он возвращает хеш с продуктом (фото) в качестве ключа, и каждый раз, когда он был заказан, он может быть указан в контексте фотографии (или нет). Используя этот метод, вы можете вывести историю заказов для каждого продукта. Не уверен, что это полезно для вас в данном контексте, но я нашел его весьма полезным. Вот код@order_items_by_photo
то выглядит примерно так:Итак, вы могли бы сделать что-то вроде:
Затем, когда вы получите это в своем представлении, просто прокрутите что-то вроде этого:
Таким образом вы избежите проблемы, возникающей при возврате только одного продукта, поскольку вы всегда знаете, что он вернет хеш с продуктом в качестве ключа и массивом ваших заказов.
Это может быть излишним для того, что вы пытаетесь сделать, но это дает вам несколько хороших вариантов (например, заказанные даты и т. Д.), С которыми можно работать в дополнение к количеству.
источник
В Rails 6 у меня получилось отлично работать:
Я не мог заставить работать другие ответы.
источник