# Overriding Date.today for a Rails app

**URL:** <https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547>\
**Category:** Rails\
**Created:** [July 4, 2007, 4:10pm UTC](https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547 "2007-07-04T16:10:16Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![johnt519](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/cab0a1/32.png) [@johnt519](https://www.ruby-forum.com/u/johnt519)\
**Post date:** [July 4, 2007, 4:10pm UTC](https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547/1 "2007-07-04T16:10:16Z")

</div>

Hey guys,

I have a time-sensitive application…not in the sense that its  
completion is urgent (although like all projects, it is), but rather  
in the sense that much of the functionality is determined by the  
actual time/date.

As a result, I’ve found that I need to freeze the concept of today  
both in development and testing (more-so in testing so that I can  
write static test sets).

I’ve started down the road of using an environment variable to store  
our date (Date.today if production, else a date that all of my tests  
can be based off of). I’m unhappy with this solution for a few  
reasons.

First, the ENV hash requires my values to be strings (try putting this  
in your environment.rb file: ENV[‘today’] = Date.new(2007, 5, 15) —  
I was shocked when I got a TypeError). As such, for this to be  
useful, I need to write a function that “hides” this  
implementation---- explicitly a reader/writer pair that converts  
between strings and dates. Since this reader/writer pair needs to be  
accessible from all parts of my application (testing, controllers,  
views), I find myself having to put this pair in multiple  
places…not very DRY.

Furthermore (and perhaps worst of all), I actually want my models to  
use this redefinition of Date.today. Now, my models _should_ be  
completely unaware that they’re being used in a Rails app, so I have a  
big problem with them knowing about this. However, I’m not sure of  
another way around it.

My last problem just stems from the fact that my whole app now needs  
to know about this “other” way to get Date.today (some global function  
defined somewhere)…just doesn’t feel right.

Another route that I considered was to reopen the Date class and  
redefine the class method “today” conditionally (based on which  
environment was loaded). However, I ran into some errors with the  
following snippet of code in my environment.rb file:

class Date  
def self.today(sg=ITALY)  
new(2007, 5, 15)  
end  
end

It’s possible the environment.rb file is the incorrect place to put  
this.

I’m open to any thoughts/suggestions/whatever. How has anyone else  
handled this problem in the past? What issues did you run into?

-John

---

<div class="post-metadata">

**Author:** ![johnt519](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/cab0a1/32.png) [@johnt519](https://www.ruby-forum.com/u/johnt519)\
**Post date:** [July 4, 2007, 4:12pm UTC](https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547/2 "2007-07-04T16:12:16Z")

</div>

I forgot to mention…the error I received when I tried to override  
the Date.today function as coded below was…

C:/Program Files (x86)/Ruby/lib/ruby/site\_ruby/1.8/rubygems/  
source\_index.rb:92:i  
n `load_specification': undefined method`_parse’ for  
Rails::Initializer:📅C  
lass (NoMethodError)  
from C:/Program Files (x86)/Ruby/lib/ruby/site\_ruby/1.8/  
rubygems/specifi  
cation.rb:13:in `today' from C:/Program Files (x86)/Ruby/lib/ruby/site_ruby/1.8/ rubygems/specifi cation.rb:314:in`date=’  
from C:/Program Files (x86)/Ruby/lib/ruby/site\_ruby/1.8/  
rubygems/specifi  
cation.rb:416:in `send' from C:/Program Files (x86)/Ruby/lib/ruby/site_ruby/1.8/ rubygems/specifi cation.rb:416:in`initialize’  
from C:/Program Files (x86)/Ruby/lib/ruby/site\_ruby/1.8/  
rubygems/specifi  
cation.rb:412:in `each' from C:/Program Files (x86)/Ruby/lib/ruby/site_ruby/1.8/ rubygems/specifi cation.rb:412:in`initialize’  
from (eval):1:in `new' from (eval):1:in`load\_specification’  
… 29 levels…  
from C:/Program Files (x86)/Ruby/lib/ruby/gems/1.8/gems/  
rails-1.2.3/lib/  
commands/server.rb:39  
from C:/Program Files (x86)/Ruby/lib/ruby/site\_ruby/1.8/  
rubygems/custom_  
require.rb:27:in `gem_original_require' from C:/Program Files (x86)/Ruby/lib/ruby/site_ruby/1.8/ rubygems/custom_ require.rb:27:in`require’  
from script/server:3

---

<div class="post-metadata">

**Author:** ![johnt519](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/cab0a1/32.png) [@johnt519](https://www.ruby-forum.com/u/johnt519)\
**Post date:** [July 4, 2007, 7:43pm UTC](https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547/3 "2007-07-04T19:43:39Z")

</div>

John T. wrote:

> As a result, I’ve found that I need to freeze the concept of today  
> both in development and testing (more-so in testing so that I can  
> write static test sets).

I had an app a while back with a similar issue. Depending on the current  
day would determine the results so I needed to be able to define “today”  
to have reliable test. Here is the result I came up with:

class Time  
class \<\< self  
# Time we might be behaving as  
attr\_reader :mock\_time

```
 # Set new time to pretend we are.
 def mock_time=(new_now)
   @mock_time = new_now
 end

 # now() with possible augmentation
 def now_with_mock_time
   mock_time || now_without_mock_time
 end
 alias_method_chain :now, :mock_time

```

end  
end

Just put this in your test\_helper.rb.

This would redefine “now” to use the value I wanted for today.  
Everything seems to flow well from that so 3.days.ago returns the right  
value. It even works with the various time zone plugins to get time  
zones working right in Rails.

So to set “today” to be Feb 1, 2006 simply do:

Time.mock\_time = Time.gm 2006, 2, 1

To restore the normal space-time continuum just:

Time.mock\_time = nil

Let me know if you need any more pointers on this.

Eric

---

<div class="post-metadata">

**Author:** ![johnt519](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/cab0a1/32.png) [@johnt519](https://www.ruby-forum.com/u/johnt519)\
**Post date:** [July 4, 2007, 8:32pm UTC](https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547/4 "2007-07-04T20:32:43Z")

</div>

This is fantastic. Thanks Eric. I’ll let you know if anything else  
comes up.

-John

---

<div class="post-metadata">

**Author:** ![johnt519](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/cab0a1/32.png) [@johnt519](https://www.ruby-forum.com/u/johnt519)\
**Post date:** [July 6, 2007, 3:16pm UTC](https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547/5 "2007-07-06T15:16:34Z")

</div>

I use a variant of the time / date mocking for testing. Also includes  
this nifty block helper, which iterates over the passed values setting  
the time to each one before executing the block…

class Date  
@@forced\_today = nil  
class \<\< self  
alias :unforced\_today :today  
def forced\_today  
return @@forced\_today ? @@forced\_today : unforced\_today  
end  
alias :today :forced\_today

```
def forced_today=(now)
  @@forced_today = now
end

```

end  
end

class DateTime  
@@forced\_now = nil  
class \<\< self  
alias :unforced\_now :now  
def forced\_now  
return @@forced\_now ? @@forced\_now : unforced\_now  
end  
alias :now :forced\_now

```
def forced_now=(now)
  @@forced_now = now
end

```

end  
end

def with\_dates(\*dates, &block)  
dates.flatten.each do |date|  
begin  
DateTime.forced\_now = case date  
when String: DateTime.parse(date)  
when Time: DateTime.parse(date.to\_s)  
else  
date  
end  
Date.forced\_today = Date.new(DateTime.forced\_now.year,  
DateTime.forced\_now.month, DateTime.forced\_now.day)  
yield  
rescue Exception =\> e  
raise e  
ensure  
DateTime.forced\_now = nil  
Date.forced\_today = nil  
end  
end  
end

put this all in your test\_helper.rb file. You can do something  
similar with Time as well.

now you can do this in your tests…

with\_dates(Date.today + 1, Date.today \>\> 1) do  
some\_code…  
end

I like this method because you can’t forget to set the clock back to  
normal.

\_Kevin

---

<div class="post-metadata">

**Author:** ![johnt519](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/cab0a1/32.png) [@johnt519](https://www.ruby-forum.com/u/johnt519)\
**Post date:** [July 6, 2007, 5:03pm UTC](https://www.ruby-forum.com/t/overriding-date-today-for-a-rails-app/108547/6 "2007-07-06T17:03:59Z")

</div>

\_Kevin wrote:

> I like this method because you can’t forget to set the clock back to  
> normal.

Looks like a nice robust implemention. I just put:

Time.mock\_time = nil

in my teardown method to make sure any time changes are reset after a  
test.

Eric
