Преобразование (слегка сложного) необработанного SQL-запроса в ActiveRecord/Arel?

У меня есть очень простое приложение Rails с очень простой реляционной базой данных: в категории много примеров. Я просто хотел бы загрузить категории, в которых есть X образцов.

В простом SQL я бы сделал что-то вроде этого:

SELECT
    categories.*
FROM
    categories
JOIN
    (SELECT
        category_id, COUNT(*) as sample_count
    FROM
        samples
    GROUP BY
        category_id
    ) AS subselect
ON
    categories.id=subselect.category_id
WHERE
    subselect.sample_count = X; -- where X is whatever

Кстати, это прекрасно работает, но использование необработанного SQL не очень похоже на Rails. И, очевидно, я хотел бы получить эти категории как экземпляры модели, поэтому:

Как мне переписать что-то подобное в запрос ActiveRecord или Arel? Возможно ли это вообще, или мне следует использовать простой SQL? Возможно, есть более простой способ сделать это?


person Flambino    schedule 26.03.2012    source источник


Ответы (1)


Возможным хорошим способом было бы использование counter_cache, как описано на этой странице: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

Добавьте столбец с именем sample_count в вашу модель категории:

add_column :categories, :samples_count, :integer

В вашем образце обновите модель own_to следующим образом:

belongs_to :category , :counter_cache => true 

Теперь вы можете использовать количество как условие, например:

Category.where(:samples_count => 7)
person dtt101    schedule 26.03.2012
comment
О, очень красиво и чисто! Я думал о добавлении столбца samples_count в категории, но не знал, что в Rails есть встроенная логика для поддержания его в актуальном состоянии (не знаю, как я это пропустил). Сам писать не хотел, поэтому и не стал :) - person Flambino; 27.03.2012