2013-10-24 61 views
0

我有一個列表模型,它有一個類別列和大小列。對於每個類別,我都有一個尺寸數組。我只想返回每個類別中與大小數組對應的列表。 (我也有設計的陣列作爲使用參數的條件[:設計者]。)將活動記錄查詢的循環減少爲一個查詢

PARAMS散列:

params[:category] => ['tops', 'bottoms', 'outerwear', 'footwear'] 
params['tops'] => ['M', 'L'] 
params['bottoms'] => [] 
params['outerwear'] => ['XL'] 
params['footwear'] => ['11', '12'] 

我已經創建了一個循環來做到這一點:

@listings = [] 
params[:category].each do |category| 
    @listings += Listing.where(category: category, size: params[category], designer: params[:designer], sold: nil).includes(:photos).page(params[:category_page]).per(@perpage) 
end 

但因爲我使用kaminari gem(.page調用)對它進行分頁,所以我需要它全部在一個查詢中。

回答

1

我結束了使用Arel這很不錯。 Arel讓你建立你想要的任何查詢,然後在Model.where()上調用它。這有點複雜,但卻是我發現的唯一解決方案。

t = Listing.arel_table 
query = t[:category].eq('rooney') 
params[:category].each do |category| 
    if params[category] 
    params[category].each do |size| 
     query = query.or(t[:category].eq(category).and(t[:size].eq(size))) 
    end 
    end 
end 
dquery = t[:designer].eq('rooney') 
params[:designer].each do |designer| 
    dquery = dquery.or(t[:designer].eq(designer)) 
end 
query = query.and(dquery) 
@listings = Listing.where(query).includes(:photos).page(params[:category_page]).per(@perpage) 

編輯:

設計者查詢可以使用.eq_any被簡化()。

t = Listing.arel_table 
query = t[:category].eq('rooney') 
params[:category].each do |category| 
    if params[category] 
    params[category].each do |size| 
     query = query.or(t[:category].eq(category).and(t[:size].eq(size))) 
    end 
    end 
end 
dquery = t[:designer].eq_any(params[:designer]) 
query = query.and(dquery) 
@listings = Listing.where(query).includes(:photos).page(params[:category_page]).per(@perpage) 
0

將其轉換爲IN查詢:

Listing.where(designer: params[:designer]).where("category IN (?)", params[:category]) 

更新:

似乎上面的代碼是不想要的運算,所以我改變了一點。如果我理解正確,您需要生成一個包含大量OR的大查詢。你可以做,沒有去阿雷爾:

params[:category] = ['tops', 'bottoms', 'outerwear', 'footwear'] 
params['tops'] = ['M', 'L'] 
params['bottoms'] = [] 
params['outerwear'] = ['XL'] 
params['footwear'] = ['11', '12'] 

query = params[:category].map do |category| 
    str = "(category = ?" 
    str += " AND size IN (?)" if params[category].any? 
    str += ")" 
    str 
end 

scope = Listing.where(query.join(" OR "), *params[:category].map { |cat| [cat, params[cat].any? ? params[cat] : nil] }.flatten(1).compact) 
scope = scope.where(designer: params[:designer], sold: nil) 
scope = scope.page(params[:per_page]).per(@page) 

它生成此查詢(分頁前):

2.0.0-p247 :095 > scope.to_sql 
=> "SELECT \"listings\".* FROM \"listings\" WHERE \"listings\".\"designer\" IS NULL AND \"listings\".\"sold\" IS NULL AND ((category = 'tops' AND size IN ('M','L')) OR (category = 'bottoms') OR (category = 'outerwear' AND size IN ('XL')) OR (category = 'footwear' AND size IN ('11','12')))" 
+0

我可能會錯過一些東西,但我不認爲這個地址在不同的類別中找到不同的尺寸。 –

1

你可以傳遞一個數組where

@listings = Listing.where(category: params[:category], s... 
+0

更棒! :) – Tumas

+0

我可能會錯過一些東西,但我不認爲這個地址在不同的類別中找到不同的尺寸。 –

+0

嗯,對,我會考慮一下 – juanpastas