Home > other >  Rails 7 Advanced Search Chain Where
Rails 7 Advanced Search Chain Where

Time:11-30

I'd like to setup an advanced search of a Rails resource (i.e Product) where I can perform both positive and negative searches. For example:

  • Product is a phone
  • Product is not made by Apple
  • Product was made in the last 16 months

I can pass multiple parameters to a page but is there a way to chain queries?

@results = Product.where("lower(type) LIKE ?", "%#{search_term.downcase}%").where(....

I'd like to use a combination of where and where.not:

  def search
    word1 = params[:word_1]
    word2 = params[:word_2]
    if word1.starts_with?('not')
      chain1 = where.not("lower(tags) LIKE ?", "%#{word1.downcase}%")
    else
      chain1 = where("lower(tags) LIKE ?", "%#{word1.downcase}%")
    end
    if word2.starts_with?('not')
      chain2 = where.not("lower(tags) LIKE ?", "%#{word2.downcase}%")
    else
      chain2 = where("lower(tags) LIKE ?", "%#{word2.downcase}%")
    end
    @products = Product.chain1.chain2
  end

but I get the following error:

undefined method where' for #ProductsController:0x0000000000ac58`

CodePudding user response:

You can chain where like this

Product.
  where(type: "phone").
  where.not(factory: "Apple").
  where(manufactered_at: 16.months.ago..)

Also rails 7 introduces invert_where (it inverts all condtions before it) so you can

Product.
  where(factory: "Apple").invert_where.
  where(type: "phone").
  where(manufactered_at: 16.months.ago..)

You can use scopes

class Product < ApplicationRecord
  scope :phone, -> where(type: "phone")
  scope :apple, -> where(factory: "Apple")
  scope :manufacatured_last, ->(period) { where(manufactered_at: period.ago..) }
end

Product.apple.invert_where.phone.manufacatured_last(16.months)
  • Related