Как создать область Rails, которая соответствует нескольким записям HABTM - PullRequest
0 голосов
/ 21 января 2019

У меня есть приложение Rails 5, действующее как CMS с моделями Story и Tag. История has_and_belongs_to_many :tags. Я хочу создать область, в которой я могу передать несколько тегов и получить все истории, в которых есть ВСЕ теги, которые я передаю.

Например:

story_1.tags   # => [tag_a, tag_c]
story_2.tags   # => [tag_b, tag_c]
story_3.tags   # => [tag_a, tag_b, tag_c]

# Desired behavior
Story.with_tags([tag_a, tag_c])  # => [story_1, story_3]
Story.with_tags([tag_b, tag_c])  # => [story_2, story_3]
Story.with_tags([tag_a, tag_b])  # => [story_3]

Я пытался создать одну область действия with_tag и объединить несколько элементов в цепочку, но, похоже, создается запрос, который пытается найти одну запись объединения, где идентификатор тега равен 1 И 3, но ничего не возвращает.

  def self.with_tag(tag)
    joins(:tags).where(tags: { id: tag })
  end

Story.with_tag(tag_a).with_tag(tag_c)  # => []

Я также пытался передать все идентификаторы тегов в одно предложение where в таблице соединений, но затем я получаю все истории, в которых есть какой-либо из тегов (более OR-запрос, я ищу AND)

  def self.with_tags(tags)
    joins(:stories_tags).where(stories_tags: { tag_id: tags }).distinct
  end

Story.with_tags([tag_a, tag_c])  # => [story_1, story_2, story_3]

1 Ответ

0 голосов
/ 21 января 2019

Вы должны использовать SQL HAVING предложение:

ids = [1,2,3]
Story.joins(:tags)
  .where(:tags => { id: ids })
  .group('stories.id')
  .having('count(tags.id) >= ?', ids.size)
#                         ^^ if you want to get stories having exactly the tags 
#                            provided, use equal instead

Аналогичный вопрос: Rails фильтрует записи во многих отношениях ко многим

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...