Suppose I have the following model, which defines a named_scope that
filters out some instances based on the current time:
class Post < ActiveRecord::Base
named_scope :current, lambda {
{ :conditions => [‘do_not_show_before < ?’, Time.now] }
}
end
I’ve been trying to come up with a good strategy for testing this,
since the test depends on time of execution. If I were using a
conventional method, say:
def self.current
find :all, :conditions => [‘do_not_show_before < ?’, Time.now]
end
I would simply rewrite it like this:
def self.current(time = Time.now)
find :all, :conditions => [‘do_not_show_before < ?’, time]
end
and then only pass in a time parameter during testing. But I don’t
know how to do with with named scopes because I cannot have optional
arguments to a block.
For right now I’ve compromised by making a required time parameter as
follows:
class Post < ActiveRecord::Base
named_scope :current, lambda { |time|
{ :conditions => [‘do_not_show_before < ?’, time] }
}
end
This means that every time I use the named_scope I have to call it
like this:
Post.current(Time.now).
I really don’t like this, but it does facilitate testing, which I
accomplish (using shoulda and factory_girl) thus:
context ‘An embargoed post’ do
setup do
@now = Time.now
@post = Factory(:post, :no_not_show_before => @now)
end
should 'be in the named_scope "current" after the
do_not_show_before datetime’ do
assert_contains Post.current(@now + 1.second), @post
end
should 'not be in the named_scope "current" before the
embargoed_until datetime’ do
assert_does_not_contain Post.current(@now - 1.second), @post
end
end
Is there a better way to accomplish this using named_scopes?
-Sven