Time-dependent values/constants in Models: An issue or not?

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':

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*?

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.

Got it - thanks a bunch !