Rails: возвращение записей, для которых связь не существует - PullRequest
8 голосов
/ 24 января 2011

Используя активную запись, как я могу вернуть результаты для модели, если они не существуют в определенных отношениях в другом месте. Например, скажем, у меня есть модель Recipe, которая принадлежит categories (через таблицу соединений category_recipes).

Так что в основном у меня есть задача Rake, которая просматривает каждый рецепт и его описание, и пытаюсь добавить в категорию, но задача занимает много времени, и мне нужно будет запускать ее регулярно, поэтому я только Я хочу запустить его, если рассматриваемый Recipe еще не был классифицирован, и я бы не стал добавлять лишний столбец, такой как categorized, поэтому я считаю, что есть способ получить только те Рецепты, которых нет присоединиться к столу. Есть мысли?

Ответы [ 5 ]

15 голосов
/ 25 января 2011

Вы можете решить этот запрос с помощью LEFT OUTER JOIN:

Recipe.joins('LEFT OUTER JOIN recipe_categories ON recipes.id = recipe_categories.recipe_id').where('recipe_categories.recipe_id IS NULL')
13 голосов
/ 19 мая 2011

Пришлось сегодня решить это самому и подумать, что это сработает:

Recipe.includes(:categories).where('categories.id IS NULL').references(:categories)
3 голосов
/ 24 января 2011

Вы можете сделать это с помощью выбора SQL, возможно.

@uncategorized_recipes = Recipe.find_by_sql("select * from recipes
  where id not in ( select recipe_id from category_recipes )")

Точный синтаксис может варьироваться в зависимости от вашей базы данных.

2 голосов
/ 04 февраля 2016

Вы можете сделать это, используя метод срыва для Recipe и CategoryReceipe.

Шаги:

  • r = Receipe.pluck (: id)

    # предоставляет массив всех идентификаторов в модели.Пример: [1, 2, 3, 4, 5 ...]

  • cr = CategoryRecipe.pluck (: recipe_id)

    #предоставляет массив всех идентификаторов из имеющегося столбца recipe_id.

  • remainder = r - cr

    # для этого используются два массива id иrecipe_id и оценивает новый массив.Этот новый массив будет иметь только те идентификаторы, которые отсутствуют в CategoryRecipe.

Затем вы можете запустить свою работу с этим новым массивом: Recipe.where (id:остаток) .count

# дает количество записей, которые необходимо обновить

Я предпочитаю этот метод, потому что вы можете превратить его в отдельную функциюкоторый вы можете использовать при оценке нескольких ассоциаций без переписывания кода.Это также чрезвычайно легко проверить.

1 голос
/ 25 января 2011

Я не проверял, но вы можете попробовать

Recipe.joins(:categories).select('recipes.*, categories.count(*) as category_count').where(:category_count => 0).group('recipes.id')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...