This is almost a FAQ because the idea seems reasonable at first.
But that isn't really how SQL works, nor data-handling operations in normal
programming languages. When you compare a type of a lower precision to a type
of a higher precision, they promote the value to the *higher* precision, and
then compare that.
For example, if you have a floating point column called myval and one row has
the value 0.5, you could obviously use where(:myval => 0.0..1.0) to find it
using floating point numbers for the range. Now you *could* write a query API
that treats integer values X as covering the entire range from X.0 to X.9999..,
so that where(:myval => 0) would find the row that had value 0.5 - but that
would be a pretty damn weird API. where(:myval => 0) and where(:myval => 0.0)
would give different results!
What you are suggesting is exactly the same idea, but instead of integers you
have dates, and instead of floats you have date-times. (These two concepts
should be a direct mapping in your head - dates are whole numbers counted since
some arbitrary start date (most of us use 1 Jan 0 CE, some things use 1 Jan
1970 for unixy reasons - whatever); times are arbitrary-precision subdivisions
of the whole days. The precision you get is even configurable per column in
many databases.)
No-one does this because it's inconsistent and although it would give the
result that you want in this situation, it produces completely counterintuitive
results in other situations.
For example, if where(:created_at => Date.yesterday) includes some row R, then
you would also expect that where("created_at <= ?", Date.yesterday) would also
find row R and so would where("created_at > ?", Date.yesterday).
Now think about how to make that work. When we see a Date value, how do we
know to treat it as 00:00:00 or 23:59:59.9999.. so that both of those where
ranges can work?
It's not possible, and so to introduce a special case for the equality case
that does not also work for inequalities and more general parameter
substitution is going to lead to a lot of very confused programmers and buggy
code.
So, like I say, SQL doesn't do this, and neither does any language binding that
I know of. There has to be one consistent rule to compare types of different
precisions, and the only sensible way to do this is to promote the lower type
to the higher precision rather than do the reverse.
That means that a date being compared to a time is always equivalent to
00:00:00 on the day, the same way that 42 being compared to a float is
equivalent to 42.0000. Making ActiveRecord do anything other would be bizarre.
Also, to ease your pain my suggestion would be that you don't write that out
manually if you do it a lot. Duckpunch a method that returns the range:
class Date
def anytime
beginning_of_day..end_of_day
end
end
User.where(:created_at => Date.yesterday.anytime)
On 6/02/2014, at 00:48 , Agis A. <[email protected]> wrote:
> When we want to find records created on a specific day, we have to do it like
> this:
>
> > User.where(created_at:
> (Date.yesterday.beginning_of_day..Date.yesterday.end_of_day)).to_sql
> => "SELECT `users`.* FROM `users` WHERE (`users`.`created_at` BETWEEN
> '2014-01-28 00:00:00' AND '2014-01-28 23:59:59')"
>
> because if we don't supply a range the following will be queried:
>
> > User.where(created_at: Date.yesterday).to_sql
> => "SELECT `users`.* FROM `users` WHERE `users`.`created_at` =
> '2014-01-28'"
>
> What if we patched AR so when we query as I do in the 2nd case, it treats it
> like it would do in the 1st query?
>
> So when I say:
>
> > User.where(created_at: Date.yesterday)
>
> It would bring me all the records that were created yesterday (from the
> beginning to the end of date).
>
> Let me know if this makes sense and is feasible, and I can prepare a PR.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Ruby on Rails: Core" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/rubyonrails-core.
> For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "Ruby
on Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/groups/opt_out.