Ruby on Rails - 选择数组中所有ID的位置

问题描述 投票:3回答:4

我正在尝试找到基于其关联和搜索数组选择记录的最简洁方法。

我有Recipes有很多Ingredients(通过连接表)我有一个搜索表单字段为arrayIngredient.ids

要查找包含搜索数组中任何ID的任何配方,我可以使用

例如1。

filtered_meals = Recipe.includes(:ingredients).where("ingredients.id" => ids)

但是,我想只匹配在搜索数组中找到所有成分的食谱。

例如2。

search_array = [1, 2, 3, 4, 5]
Recipe1 = [1, 4, 5, 6]
Recipe2 = [1, 3, 4]
# results => Recipe2

我知道我可以使用each循环,就像这样;

例如3。

filtered_meals = []

 Recipes.each do |meal|
   meal_array = meal.ingredients.ids
   variable =  meal_array-search_array
     if variable.empty?
       filtered_meals.push(meal)
     end
   end
 end

 return filtered_meals

这里的问题是分页。在第一个例子中,我可以使用.limit().offset()来控制显示多少结果,但在第三个例子中,我需要添加一个额外的计数器,提交结果,然后在页面更改时,重新发送计数器并在.drop(counter)循环上使用each.do

这似乎太长了,有没有更好的方法呢?

ruby-on-rails arrays ruby postgresql select
4个回答
1
投票

假设您使用的是has_many through和recipe_id,则ingredient_id组合是唯一的。

recipe_ids = RecipeIngredient.select(:recipe_id)
                             .where(ingredient_id: ids)
                             .group(:recipe_id)
                             .having("COUNT(*) >= ?", ids.length)
filtered_meals = Recipe.find recipe_ids

0
投票

Ruby on Rails Guide 2.3.3 - Subset Conditions

Recipe.all(:ingredients => { :id => search_array })

应该导致:

SELECT * FROM recipes WHERE (recipes.ingredients IN (1,2,3,4,5))

在SQL中。


0
投票

数组&运算符会在这里为你工作吗?

就像是:

search_array = [1, 2, 3, 4, 5]
recipe_1 = [1, 4, 5, 6]
recipe_2 = [1, 3, 4]

def contains_all_ingredients?(search_array, recipe)
  (search_array & recipe).sort == recipe.sort
end

contains_all_ingredients(search_array, recipe_1) #=> false
contains_all_ingredients(search_array, recipe_2) #=> true

此方法比较数组并仅返回两者中存在的元素,因此如果比较结果等于配方数组,则全部都存在。 (显然,您可以通过一些重构来使方法位于配方模型中。)

然后你可以这样做:

Recipes.all.select { |recipe| contains_all_ingredients?(search_array, recipe) }

我不确定它通过你的例子三,但可能会帮助你的方式?让我知道如果开始没问题,我会在此期间有更多的想法/如果它有用:)


0
投票

怎么样

filtered_meals = Recipe.joins(:ingredients)
                       .group(:recipe_id)
                       .order("ingredients.id ASC")
                       .having("array_agg(ingredients.id) = ?", ids)

您需要确保您的ids参数按升序列出,以便数组中元素的顺序也匹配。

© www.soinside.com 2019 - 2024. All rights reserved.