Question

I'm trying to recreate the following syntax using squeel by using a loop:

WHERE season = "value" OR season IS NULL

I was able to get this far:

where do
  ((season == entry["season"]) | (season == nil)) &
  ((episode == entry["episode"]) | (episode == nil)) &
  ((imdb == entry["imdb"]) | (imdb == nil)) &
  (YEAR(theatrical) == year)

However, the problem is I want to do it in a loop so I don't have to do conditionals for when the values are empty (for example if imdb doesn't have a value I wouldn't even use that line).

I have this:

entry = { "imdb"=>"0364725", "media"=>"DVD", "season"=>"1", ...}
entry.each do |k,v|
    ((k == v) | (k == nil))
  end
end

But it does not put the field IS NULL bit in the SQL.

If it's not possible with Squeel, might it be done with ActiveRecord?

Ultimately, I'm looking for a way to avoid having conditionals for those fields in the SQL. As I said above, if the field is empty I don't list them at all, but if it has a value I need to do the whole field = value OR field IS NULL bit.

Any help would be greatly appreciated.

Edit:

The whole code I'm trying to use at the moment is this:

matches_found = 
includes(:dvd_director, :dvd_upc, :dvd_series).limit(1).
where do
  (title == title_to_search) &
  entry.each { |k,v| ((k == v) | (k == nil)) }
end

Note that everything after the | is getting ignored whether I use __send__(k) or not.

More info: One very strange thing is that if I use anything other than the k,v it gets ignored. For example:

    entry.each { |k,v| ((k == "bob") | (k == v)) }

"Bob" gets ignored! and the value (v) gets put into the SQL without the OR statement.

Was it helpful?

Solution 2

In the end, the only solution I could come up with was to add nil into the array itself for Squeel to process it properly:

entry.each do |k,v| 
   # we add a nill value so Squeel will do the OR field IS NULL
   entry[k] = [v, nil] if k == "upc" || k == "asin" || k == "freebase" || k == "imdb" 
end

This is ugly but it works. Now I'm sure there is a nicer way to write all those or's in the 3rd line but that's another question :)

OTHER TIPS

If I understood correctly, you need __send__:

where do
  (title == title_to_search) & entries.map do |k, v| 
    (__send__(k) == v) | (__send__(k) == nil)
    # or: __send__(k) >> [v, nil]
  end.inject(:&)
end

https://github.com/ernie/squeel/wiki/Tips-and-tricks

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top