altkatz
altkatz

Reputation: 107

Remove duplicate in ActiveRecord habtm query results

I have two models has_and_belong_to_many to each other:

class Post < ActiveRecord::Base
  has_and_belongs_to_many :tags, :join_table => :tags_posts
end

class Tag < ActiveRecord::Base
  has_and_belongs_to_many :posts, :join_table => :tags_posts
end

And then I have a query:

@tags = Tag.where(name: ["tag1","tag2","tag3"])

I want to get all the unique posts that have these tags, so I write this ugly code:

@posts = [] 
@tags.each do |tag|
  @posts += tag.posts
end
@posts.uniq!

I guess it's inefficient, and since @posts is an array rather than a "ActiveRecord::Relation", I can't use all the class methods on it directly. Is there a better way to achieve this?

Upvotes: 0

Views: 1068

Answers (2)

Rajesh Kolappakam
Rajesh Kolappakam

Reputation: 2125

You could join the two tables using includes and query on the Post model rather than Tag so that you get unique posts.

Post.includes(:tags).where(:tags => { name: %w(tag1 tag2 tag3) })

Upvotes: 1

iGEL
iGEL

Reputation: 17392

@tags = Tag.where(name: %w(tag1 tag2 tag3)).includes(:posts)

should do the trick (%w() creates an array of strings, so no difference). It loads all posts with the tags in one or two queries, whatever is more efficient in AR's view. And then you can do

@posts = @tags.map(&:posts).flatten.uniq

to get the posts. map calls posts method on every tag and returns an array with those posts, but since you have an array of arrays, you want to flatten it.

Upvotes: 2

Related Questions