0

我有一个列表模型,它有一个类别列和一个大小列。对于每个类别,我都有一系列尺寸。我只想返回与大小数组对应的每个类别中的列表。(我也有一组设计师作为 params[:designer] 的条件。)

参数哈希:

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 调用)对其进行分页。

4

3 回答 3

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)
于 2013-10-25T19:39:23.700 回答
1

您可以将数组传递给where

@listings = Listing.where(category: params[:category], s...
于 2013-10-24T21:35:57.773 回答
0

将其转换为 IN 查询:

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

更新:

似乎上面的代码不是 op 想要的,所以我对其进行了一些更改。如果我理解正确,您需要生成一个包含大量 OR 的大查询。你可以做到这一点,而无需去 arel:

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')))"
于 2013-10-24T21:35:18.160 回答