Rails Searchkick with scopes in controller

I'm making a search page where I have a couple of filters on the side and I'm trying to integrate them with Searchkick to query products.

These are my scopes I'm using for the products

models/product.rb

scope :in_price_range, ->(range) { where("price <= ?", range.first) }    
scope :in_ratings_range, -> (range) { where("average_rating >= ?", range.first) }

def self.with_all_categories(category_ids)
    select(:id).distinct.
    joins(:categories).
    where("categories.id" => category_ids)
end

This is where I'm actually calling the scopes

controllers/search_controller.rb

@results = Product.search(@query)
@results = @results.with_all_categories(params[:category_ids]) if params[:category_ids].present?
@results = @results.in_price_range(params[:price]) if params[:price].present?
@results = @results.in_ratings_range(params[:rating]) if params[:rating].present?

After running it, I get an error saying the searchkick model doesn't have any methods with the name of my scope.

undefined method `with_all_categories' for #Searchkick::Results:0x00007f4521074c30>

How do I use scopes with my search query?

Upvotes: 2

Views: 1315

Answers (2)

Andrew Kane
Andrew Kane

Reputation: 3236

You can apply scopes to Searchkick results with:

Product.search "milk", scope_results: ->(r) { in_price_range(params[:price]) }

See "Run additional scopes on results" in the readme.

However, if you apply ActiveRecord where filters, it will throw off pagination. For pagination to work correctly, you need to use Searchkick's where option:

Product.search(query, where: {price_range: 10..20})

Upvotes: 5

Jagdeep Singh
Jagdeep Singh

Reputation: 4920

The error (unknown to me at the time of writing this answer) might be because you defined with_all_categories as a class method on Product, but in your controller you call it on @results which must be an ActiveRecord::Relation.

Turning it into a scope should fix the issue:

Change this:

def self.with_all_categories(category_ids)
  select(:id).distinct.
    joins(:categories).
    where("categories.id" => category_ids)
end

to:

scope :with_all_categories, -> (category_ids) { select(:id).distinct.joins(:categories).where("categories.id" => category_ids) }

Upvotes: 0

Related Questions