1

Say i had a record in my database like

+----+-----------+----------+
| id | firstname | lastname |
+----+-----------+----------+
|  1 | 'Bill'    | nil      |
+----+-----------+----------+

(note last name is nil)

Is there any where I can retrieve the above record using the following hash structure as search parameters:

vals = {firstname: "Bill", lastname: "test"}
Table.where(vals)

(ie: find the closest match, ignoring the nil column value in the table)

(I'm thinking of checking each key in the hash individually and stopping when a match is found, but just wondering if there is a more efficient way, specially for larger tables)

L457
  • 1,002
  • 1
  • 13
  • 33

2 Answers2

3

You could make custom search.

def self.optional_where params
   query_params = params.keys.map do |k|
      "(#{k} = ? OR #{k} IS NULL)"
   end.join(" AND ")
   where(query_params, *params.values)
end

Then you would use it like

Table.optional_where(vals)

This will produce next query

SELECT "tables".* FROM "tables" WHERE ((firstname = 'Bill' OR first_name IS NULL) AND (lastname = 'test' OR last_name IS NULL))
Nermin
  • 6,118
  • 13
  • 23
0

Let make a custom search like this:

scope :custom_search, -> (params) {
  params.each do |k, v|
    params[k] = if
      if v.is_a? Array
        (v << nil).uniq
      else
        [v, nil]
      end
    where(params)
  end
}

Then we use it like:

search_params = {firstname: "Bill", lastname: "test"}
Table.custom_search(search_params)

The generated sql will be:

SELECT * FROM tables where firstname IN ['Bill', null] AND lastname IN ['test', null]

This means you don't care if one or more fields are nil

Hieu Pham
  • 6,577
  • 2
  • 30
  • 50