Skip to content

Instantly share code, notes, and snippets.

@casperbrike
Created January 31, 2021 09:10
Show Gist options
  • Save casperbrike/9c71185338b56a71189c63f44c9387db to your computer and use it in GitHub Desktop.
Save casperbrike/9c71185338b56a71189c63f44c9387db to your computer and use it in GitHub Desktop.
How to find Books that belong to desired Categories with Rails?
# The logic here is dishonestly stolen from Gutentag gem:
# https://github.com/pat/gutentag/blob/0dbcd1dbcd4de8930e589cf964498abe46127a98/lib/gutentag/tagged_with/query.rb#L11
# Models definitions
class Book < ApplicationRecord
has_many :category_mappings, as: :categorizable, dependent: :destroy
has_many :categories, through: :category_mappings
end
class CategoryMapping < ApplicationRecord
belongs_to :category
belongs_to :categorizable, polymorphic: true
end
class Category < ApplicationRecord
has_many :category_mappings, dependent: :restrict_with_error
end
# Let's assume we want to find books that belong to all categories below,
# i.e. every book belongs to "Detective" AND "Fiction" categories.
searched_categories = %w[Detective Fiction]
# The most important part where magic happens.
sub_query =
CategoryMapping
.joins(:category)
.select(:categorizable_id)
.where(categorizable_type: Book.base_class.name)
.where(Category.table_name => { name: searched_categories })
.group(:categorizable_id)
.having("COUNT(*) = #{searched_categories.size}")
.to_sql
books_table_id = "#{Book.quoted_table_name}.#{Book.quoted_primary_key}"
# Resulting query that returns desired Books
Book.where("#{books_table_id} IN (#{sub_query})")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment