Search code examples
ruby-on-railspostgresqlarelransack

ILIKE for multiple columns with Arel and Ransack


I am using Ransack search with a Postgresql DB.

I have an input that I need to search using "ILIKE" (text column) in two different columns.

First I created this ransacker:

ransacker :number do
  Arel.sql("invoice_number::text")
end

That works fine:

Purchase.ransack({number_cont: "123"}).result.to_sql
# => "SELECT \"purchases\".* FROM \"purchases\" WHERE (invoice_number::text ILIKE '%123%')"

However, I want now to search in another column using the same input (so, same ransacker).

I tried doing this:

ransacker :number do |parent|
  Arel::Nodes::InfixOperation.new('OR', parent.table["invoice_number::text"], parent.table["shipping_number::text"])
end

Which returns:

Purchase.ransack({number_cont: "123"}).result.to_sql
# => "SELECT \"purchases\".* FROM \"purchases\" WHERE (\"purchases\".\"invoice_number::text\" OR \"purchases\".\"shipping_number::text\" ILIKE '%123%')"

So as you can see isn't so different from what I need, which is:

"column1::text ILIKE '%123%' OR column2::text ILIKE '%123%'"

Do you know how can I achieve that?


Solution

  • This isn't precisely what you're wanting, but it looks like with the ransack gem, if you combine multiple fields in the query param name it works:

    class Purchase < ApplicationRecord
      ransacker :number do
        Arel.sql("invoice_number::text")
      end
    
      ransacker :shipping do
        Arel.sql("shipping_number::text")
      end
    end
    
    puts Purchase.ransack(shipping_or_number_cont: '123').result.to_sql
    # => SELECT "purchases".* FROM "purchases"
    #  WHERE (shipping_number::text LIKE '%123%' OR invoice_number::text LIKE '%123%')
    

    So if you're able to tweak the param name, this may be easier than trying to do it inside the ransacker block