[ruby-on-rails] 관계를 통해 has_many의 고유 레코드를 표시하는 방법은 무엇입니까?

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

다른 답을 얻지 못했습니다.


답변