Hi there,
I remember reading in the comments of a Rails blog something along these
lines:
“Since a Model is loaded only once in production development (at server
start), certain time-dependent ‘constants’ that you have placed in a
method of a Model will always return the same value for those
‘constants’, i.e. the value the ‘constant’ had at server start.”
Hypothetic example for the MySQL ‘constant’ “UTC_TIMESTAMP()” in a Model
‘User’:
=====
def books_created_right_now
self.books.find(:all, :conditions => “books.updated_at =
UTC_TIMESTAMP()”)
end
Is the above statement utter BS or is there actually some issue similar
to the example or statement?
Thanks a lot!
Tom
On Jun 26, 2010, at 6:00 AM, Tom Ha wrote:
Hypothetic example for the MySQL ‘constant’ “UTC_TIMESTAMP()” in a Model
to the example or statement?
The above example is perfectly okay. However, the below isn’t:
named_scope :books_created_right_now, :conditions => [“updated_at = ?”,
Time.now]
The reason the above fails is that Time.now is evaluated once when the
class is loaded. To get around that you can use a lambda for the named
scope.
named_scope :books_created_right_now, lambda { {:conditions =>
[“updated_at = ?”, Time.now]} }
Or, for example you wouldn’t want to do this:
class Book << AR
NOW = Time.now
use NOW somewhere in a method thinking it’s still going to be ‘now’
end
I believe that is what the documents are referring to.
Thanks a lot for your explanation (I believe a lot of folks are not
necessarily aware of this “detail”…).
One question back, though:
Is the issue rather…
a) with Rails’ “Time.now” VS MySQL’s “UTC_TIMESTAMP()” (where the former
would never return the “true now” when used anywhere within a Class
and the latter would always be returned as the “true now”), or is the
issue…
b) with the context of the “time constant” (equally in both cases),
where the constant would always return the “true now” if it is used:
-
within a method of a Class, or
- within a named_scope, together with a lambda,
- but NOT outside of a method within a Class?
You also say:
The reason the above fails is that Time.now is evaluated once when the
class is loaded.
-> Are a Class’ methods not also evaluated only once?
Got it - thanks a bunch !
On Jun 28, 2010, at 11:42 AM, Tom Ha wrote:
issue…
class is loaded.
-> Are a Class’ methods not also evaluated only once?
No. The danger is that you might assign the result of Time.now to a
class variable or constant. Or use it in a spot that is evaluated
only once (like my first named_scope example) and not realize it.
class Foo
NOW = Time.now
def self.klass_meth
puts Time.now.to_s + ’ ’ + NOW.to_s
end
def inst_meth
puts Time.now.to_s + ’ ’ + NOW.to_s
end
end
Foo.klass_meth
sleep 1
Foo.klass_meth
sleep 1
f = Foo.new
sleep 1
f.inst_meth
sleep 1
f.inst_meth
Mon Jun 28 12:25:36 -0700 2010 Mon Jun 28 12:25:36 -0700 2010
Mon Jun 28 12:25:37 -0700 2010 Mon Jun 28 12:25:36 -0700 2010
Mon Jun 28 12:25:39 -0700 2010 Mon Jun 28 12:25:36 -0700 2010
Mon Jun 28 12:25:40 -0700 2010 Mon Jun 28 12:25:36 -0700 2010