I'd advise against using string interpolation for this, there are many sharp edges and you'll probably have more fun bobbing for apples in a bucket of fish hooks. You should do it this way:
Model.where(
'created_at >= :five_days_ago or updated_at >= :three_days_ago',
:five_days_ago => Time.now - 5.days,
:three_days_ago => Time.now - 3.days
)
Using (well) named placeholders gives you the readability and position independence that you think string interpolation offers but nicely sidesteps the quoting, timezone, and format issues that string interpolation forces on you.
But how do you safely use string interpolation? There are a few things you must handle yourself:
- Quoting and escaping.
- Timestamp formats.
- Maybe timezones too.
ActiveRecord will take care of all this nonsense for you.
Don't try to do the quoting yourself, use the driver's quoting methods. You will have access to connection.quote
for properly quoting strings.
Any database will know what to do with ISO 8601 timestamps and there is a convenient iso8601
method for that. ISO 8601 also conveniently includes the timezone and the database should be able to parse that (but if it can't then you'll have to convert your times to UTC by hand with .utc
).
So, to be safe:
Model.where("created_at >= #{connection.quote((Time.now - 5.days).utc.iso8601)} " + \
"OR updated_at >= #{connection.quote((Time.now - 3.days).utc.iso8601)}")
Not so pretty now is it? With ISO 8601 timestamps you should be safe replacing the connection.quote
calls with simple single quotes:
Model.where("created_at >= '#{(Time.now - 5.days).utc.iso8601}' " + \
"OR updated_at >= '#{(Time.now - 3.days).utc.iso8601}'")
but you still have a lot of noise and ugliness and you'll be developing bad habits.
We're not partying like PHP programmers in 1999 so don't give in to false laziness by using string interpolation in your SQL, use named placeholders.