2012-06-05 32 views
6

Tôi có một mô hình Producthas_and_belongs_to_many :taxons và tôi muốn tìm tất cả các sản phẩm nằm trong các loại thuế cụ thể. Ví dụ: nếu một sản phẩm thuộc về cả thuế "Ruby on Rails" và "Shirts", tôi muốn sản phẩm đó được trả lại trong tập dữ liệu, nhưng không phải là nếu nó chỉ thuộc về một trong hai "Ruby on Rails" "hay 'Áo sơ mi'Tìm các bản ghi có hai bản ghi cụ thể trong một bảng khác

Trả lời

13

tôi có vấn đề này trong một thời gian trở lại, may mắn có một giải pháp tốt đẹp.

def self.has_taxons(taxons) 
    id = arel_table[:id] 
    Product.joins(:taxons).where(taxons: { name: taxons }).group(id).having(id.count.eq(taxons.size)) 
end 
+1

Một internet cho bạn, thưa bạn. –

+0

@RyanBigg Ngoài ra hãy xem đá quý này: https://github.com/ernie/squeel. Nó thêm một lớp trừu tượng trên ARel. Nó cho phép bạn xây dựng các truy vấn súc tích/dễ đọc hơn. Ngay cả khi 'taxons.name.in taxons' hoặc' taxons.name >> taxon' không tốt hơn nhiều so với băm lồng nhau, bạn sẽ đánh giá cao chuỗi này nếu bạn cần nhiều hơn 2 cấp độ tham gia. Và bạn có thể làm cho công cụ 'có' của bạn w/o gọi' arel_table', như: 'có {count (id) == some_size}'. – jdoe

0

hiệu suất Giả sử không phải là một yêu cầu:

a = Taxon.find_by_name!('Ruby on Rails').products.pluck(:id) 
b = Taxon.find_by_name!('Shirts').products.where(:id => a) 
1

Câu trả lời này từ @samuel là chính xác những gì tôi đang tìm kiếm, nhưng tôi muốn để có thể vẫn cung cấp từ khóa để tìm kiếm trong khi lọc theo Taxon1 VÀ Taxon2 và TaxonN. Tôi không bao giờ cần phải thực hiện tìm kiếm Taxon1 HOẶC Taxon2, vì vậy tôi đã thực hiện các tùy chỉnh sau. Có thể có một cách ít hacky để làm điều này, nhưng nó hoạt động tuyệt vời cho tôi.

Tôi đã thêm một phạm vi sản phẩm mới trong /app/models/spree/product_decorator.rb

Spree::Product.class_eval do 
    add_search_scope :in_all_taxons do |*taxons| 
     taxons = get_taxons(taxons) 
     id = arel_table[:id] 
     joins(:taxons).where(spree_taxons: { id: taxons }).group(id).having(id.count.eq(taxons.size)) 
    end 
end 

Sau đó, sử dụng phạm vi mới bằng cách thêm vào /app/models/spree/base_decorator.rb

Spree::Core::Search::Base.class_eval do 
    def get_base_scope 
     base_scope = Spree::Product.active 
     base_scope = base_scope.in_all_taxons(taxon) unless taxon.blank? 
     base_scope = get_products_conditions_for(base_scope, keywords) 
     base_scope = add_search_scopes(base_scope) 
     base_scope 
    end 
end 

Bây giờ tôi có thể sử dụng các helper tìm kiếm chuẩn để lấy sản phẩm (có nghĩa là tôi vẫn có thể cung cấp từ khóa, vv cùng với nhiều taxons):

# taxon_ids is an array of taxon ids 
@searcher = build_searcher(params.merge(:taxon => taxon_ids)) 
@products = @searcher.retrieve_products 

Điều này làm việc cho tôi và cảm thấy khá đau. Tuy nhiên, tôi đang mở để lựa chọn tốt hơn.

Các vấn đề liên quan