krn
krn

Reputation: 6815

Proc.new in Ruby: when do I need to use it?

The date_validator in its examples has a comment:

Using Proc.new prevents production cache issues

Does it mean, that everywhere in my code, where I use current time related methods (Time.now, 1.day.since(Time.zone.now), etc.) I should surround them with Proc.new { }?

I don't completely understand this, since replacing

time_now = Time.now.utc

with

time_now = Proc.new { Time.now.utc }

just doesn't make sense to me (new type of object is returned).

So, the question is, when and how should I use Proc.new with time related methods? And does that still apply to the latest versions of Ruby (1.92) and Rails (3.1)?

Upvotes: 3

Views: 1402

Answers (2)

Jakob S
Jakob S

Reputation: 20125

No, it only references the given example:

validates :expiration_date,
  :date => {:after => Proc.new { Time.now },
  :before => Proc.new { Time.now + 1.year } }

If instead you'd written

validates :expiration_date,
  :date => {:after => Time.now,
  :before => Time.now + 1.year }

Time.now would be interpreted when the class is parsed and it would be validating against that value.

Using Proc.new in that validation means Time.new will be evaluated when the validation is actually run - not when it's initially being interpreted.

Upvotes: 5

Dogbert
Dogbert

Reputation: 222040

What Proc.new (and lambda) does is, save all your statements in their original form (in an anonymous function), and doesn't evaluate them.

Date Validator gem must have some kind of test to check if a Proc was passed, and it evaluates it when it's actually validating the stuff.

Edit: It does this here - https://github.com/codegram/date_validator/blob/master/lib/active_model/validations/date_validator.rb#L47

option_value = option_value.call(record) if option_value.is_a?(Proc)

A quick example :

pry(main)> time_now = Time.now
=> 2011-06-19 21:07:07 +0530
pry(main)> time_proc = Proc.new { Time.now }
=> #<Proc:0x9710cc4@(pry):1>
pry(main)> time_proc.call
=> 2011-06-19 21:07:28 +0530
pry(main)> time_proc.call
=> 2011-06-19 21:07:31 +0530
pry(main)> 

Note that this will only work with libraries that do implement this kind of check, and not every function accepting a Time.

Upvotes: 3

Related Questions