jorgeregidor
jorgeregidor

Reputation: 208

Rails query with more than one nested attributes

I have two models in my rails 5 application:

class Post < ApplicationRecord
  has_many :tags
end

class Tag < ApplicationRecord
  belongs_to :post
end

In my data base I have for example two post with 2 different tags each. How can I search my post by two specifics tags (tag.title="tagname1" AND tag.title="tagname2"):

Post.includes(:tags).where(tag: {title: "tagName1"}).where(tag: {title: 
"tagName2"})

thanks

Upvotes: 2

Views: 2103

Answers (3)

Jay-Ar Polidario
Jay-Ar Polidario

Reputation: 6603

Solution

Post.joins(:tags)
  .where(tags: { title: ['tag1', 'tag2'] })
  .group('posts.id')
  .having('count(tags.post_id) = ?', 2)

Assumptions:

  • you have a uniqueness validation for tag.title for each post like the following:

    class Tag < ApplicationRecord
      belongs_to :post
    
      validates :title, uniqueness: { scope: :post }
    end
    

    ... otherwise, solution above won't work, because:

    # it will still also match the following Post
    Post(id: 1)
      Tag(post_id: 1, title: 'tag1')
      Tag(post_id: 1, title: 'tag1')
    
    # but that you only want instead those like the following:
    Post(id: 2)
      Tag(post_id: 2, title: 'tag1')
      Tag(post_id: 2, title: 'tag2')
    

Upvotes: 2

Anand
Anand

Reputation: 6531

search post by two specifics tags

Post.includes(:tags).where("tags.title IN (?)",["tagName1", "tagName"]).references(:tag)

This will return all posts having tags.title either "tagName1" or "tagName"

Upvotes: 0

Nermin
Nermin

Reputation: 6100

You could use arel for cleaner queries.

Post.joins(:tags).where(Tag.arel_table[:title].in(['tagName1', 'tagName']))

Upvotes: 1

Related Questions