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 !