我会考虑使用Arel来解决这类问题太复杂了。 ActiveRecord本身,这是Arel上面的一层可以很舒服地解决这个问题。
我假设你有以下型号
class Recipe
has_many :recipe_ingredients
...
end
class RecipeIngredient
has_one: :recipe
has_one: :ingredient
...
end
class Ingredient
has_many :recipe_ingredients
...
end
为了得到通过配料的数量排序的食谱,你就必须产生下面的SQL语句:
SELECT
recipes.id
...
, recipes.[last_column_name]
# optionally
, COUNT(*) ingredients_count
FROM
recipes
OUTER JOIN
recipe_ingredients
ON
recipe_ingredients.recipe_id = recipe.id
GROUP BY
ingredient_count DESC
从而可以由
Recipe
.joins(:recipe_ingredients)
.group(Recipe.column_names)
.select(Recipe.column_names, 'COUNT(*) ingredients_count')
.order('ingredients_count DESC') # Or ASC
返回的食谱实例将按数量排序配料。他们还将有一个额外的方法ingredients_count
,它返回配料的数量。
这也可以放在配方类的范围内。
def self.ordered_by_ingredients_count
joins(:recipe_ingredients)
.group(column_names)
.select(column_names, 'COUNT(*) ingredients_count')
.order('ingredients_count DESC') # Or ASC
end
对于反向,配方数量的成分在,只是交换一些名字:
Ingredient
.joins(:recipe_ingredients)
.group(Ingredient.column_names)
.select(Ingredient.column_names, 'COUNT(*) recipe_count')
.order('recipe_count DESC') # Or ASC