Detect sloppy use of dates and times in ActiveRecord scopes
Ruby JavaScript
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
demo
lib
.gitignore
Gemfile
LICENSE
README.md
Rakefile
sloppy_time.gemspec

README.md

SloppyTime

One of the sloppy mistake you could make when defining scopes in ActiveRecord models is that you pass dates and times to its arguments:

class Post < ActiveRecord::Base
  scope :last_week, where('created_at < ?', Time.zone.now)
end

This is wrong because Time.zone.now is only evaluated once when post.rb is loaded. You have to use lambda instead:

class Post < ActiveRecord::Base
  scope :last_week, lambda { where('created_at < ?', Time.zone.now) }
end

This gem tries to detect such mistakes by overriding Time.now, Date.today and DateTime.now and scanning the caller code if the line matches with /(named_)?scope/. (Yeah it's silly)

The idea is to enable this gem with the test bundler group and running your unit tests will emit the warnings like following:

WARNING: Your model has a scope with Time evaluated immediately. You might have to use lambda instead.
/path/to/demo/app/models/post.rb:2:   scope :last_week, where('created_at < ?', Time.zone.now)

See Working with times in the Rails guide for more details.

Installation

Add this line to your application's Gemfile:

group :test do
  gem 'sloppy_time'
end

And then execute:

$ bundle

Usage

Add it to Gemfile and you're all set. Be sure to only activate it in test and/or development bundler groups, because it is silly to enable this gem on production.

Author

Tatsuhiko Miyagawa (@miyagawa), inspired by the ideas from Kenta Murata (@mrkn) and Shingo Morita (@eudoxa).