2

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?

2 Answers2

5

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})
Andrew Kane
  • 3,200
  • 19
  • 40
  • Is there a way to get Searchkick's pagination to play nicely with ActiveRecord's where? I have a custom scope that uses joins etc that would be a hassle to reconstruct... – emersonthis Jul 11 '22 at 17:51
0

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) }
Jagdeep Singh
  • 4,880
  • 2
  • 17
  • 22