Rails3의 관계를 통해 has_many의 고유 레코드를 표시하는 가장 좋은 방법이 무엇인지 궁금합니다.
세 가지 모델이 있습니다.
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 연관에 : uniq 옵션을 지정하려고 했습니까?
has_many :products, :through => :orders, :uniq => true
에서 레일 문서 :
:uniq
true 인 경우 컬렉션에서 중복 항목이 생략됩니다. : through와 함께 유용합니다.
레일 4 업데이트 :
Rails 4에서는 has_many :products, :through => :orders, :uniq => true
더 이상 사용되지 않습니다. 대신 이제 has_many :products, -> { distinct }, through: :orders
. 자세한 정보 는 ActiveRecord 연관 문서에서 has_many : : through 관계에 대한 구별 섹션 을 참조하십시오. 그의 의견에서 이것을 지적한 Kurt Mueller에게 감사드립니다.
답변
참고 uniq: true
를 위해 유효한 옵션에서 제거 된 has_many
레일 (4)로.
Rails 4에서는 이런 종류의 동작을 구성하기 위해 범위를 제공해야합니다. 범위는 다음과 같이 람다를 통해 제공 될 수 있습니다.
has_many :products, -> { uniq }, :through => :orders
레일 가이드에서는 범위를 사용하여 관계의 쿼리를 필터링 할 수있는이 방법과 기타 방법을 다룹니다. 섹션 4.3.3으로 스크롤합니다.
http://guides.rubyonrails.org/association_basics.html#has-many-association-reference
답변
당신은 사용할 수 있습니다 group_by
. 예를 들어, 주문 항목을 어떤 사진별로 정렬하려는 사진 갤러리 쇼핑 카트가 있습니다 (각 사진은 여러 번 주문할 수 있고 다른 크기로 인쇄 할 수 있음). 그러면 제품 (사진)이 키로 포함 된 해시가 반환되고 주문 될 때마다 사진의 컨텍스트에 나열 될 수 있습니다 (또는 그렇지 않음). 이 기술을 사용하면 주어진 각 제품에 대한 주문 내역을 실제로 출력 할 수 있습니다. 이 맥락에서 그것이 당신에게 도움이되는지 확실하지 않지만 나는 그것이 매우 유용하다는 것을 알았습니다. 다음은 코드입니다.
OrdersController#show
@order = Order.find(params[:id])
@order_items_by_photo = @order.order_items.group_by(&:photo)
@order_items_by_photo
그러면 다음과 같이 보입니다.
=> {#<Photo id: 128>=>[#<OrderItem id: 2, photo_id: 128>, #<OrderItem id: 19, photo_id: 128>]
따라서 다음과 같이 할 수 있습니다.
@orders_by_product = @user.orders.group_by(&:product)
그런 다음 뷰에서 이것을 얻을 때 다음과 같이 반복하십시오.
- for product, orders in @user.orders_by_product
- "#{product.name}: #{orders.size}"
- for order in orders
- output_order_details
이렇게하면 하나의 제품 만 반환 할 때 나타나는 문제를 방지 할 수 있습니다. 제품이 키로 포함 된 해시와 주문 배열이 반환된다는 것을 항상 알고 있기 때문입니다.
그것은 당신이하려는 일에 과잉 일 수 있지만, 수량 외에도 작업 할 수있는 좋은 옵션 (예 : 주문한 날짜 등)을 제공합니다.
답변
Rails 6에서 완벽하게 작동하도록했습니다.
has_many :regions, -> { order(:name).distinct }, through: :sites
다른 답을 얻지 못했습니다.