Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Rails plugin providing a parent object for has_many associations based on time, rather than a foreign key.
Ruby
tree: e76ead4801

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
tasks
test
MIT-LICENSE
README.textile
Rakefile
init.rb
install.rb
uninstall.rb

README.textile

ActiveTime

ActiveTime is a Rails plugin that provides a parent object for has_many-ish associations to other ActiveRecord classes, but instead of a foreign key to scope the queries, a date range is used instead.

A year has many posts, a month has many comments, etc.

A few quick examples:

# All Posts created in 2008
ActiveTime.new(2008).posts

# All Users created on November 15, 2008
ActiveTime.new(2008, 11, 15).users  

# All Comments created between two specific Times
ActiveTime.new(1.year.ago.utc, Time.now.utc).comments

# You aren't stuck with created_at either
ActiveTime.new(2008).posts(:published_at)

# It's a named_scope under the hood, so you can do normal stuff:
ActiveTime.new(2008).posts.public.newest_first.paginate

Installation

./script/plugin install git://github.com/justinfrench/active_time.git

Why?

I’m not sure why you need it, but I’m building some RESTful controllers that need to present resources in a hierarchy based on dates (rather than a typical has_many/belongs_to association), so I wanted a model for the resource, upon which I could do the usual ActiveRecord has_many associations, scope chaining, pagination, etc.

How?

Firstly, the plugin adds a named scope to ActiveRecord::Base (so it’s added to all your AR classes) called in_date_range, which you can use directly if needed. It takes two Time objects in UTC as arguments (start time, end time) and optionally, a third argument that specifies which column the date range applies to (the default is :created_at). Examples:

Post.in_date_range(1.year.ago.utc, Time.now_utc)
Post.in_date_range(1.year.ago.utc, Time.now_utc, :published_at)

If you have two Time objects for the start and end of the range, ActiveTime is simply a wrapper around this named scope. These both result in the same database query:

Post.in_date_range(1.year.ago.utc, Time.now_utc)
ActiveTime.new(1.year.ago.utc, Time.now.utc).posts

Given that the second version is two characters longer, it’s not all that impressive, but what I really needed was to pass in just the start date, or part of one (like params[:year]) and automatically figure out what range I wanted (a whole year, a month, a day).

ActiveTime.new(params[:year]).posts
ActiveTime.new(params[:year], params[:month]).posts

And there’s more!

  
# Get the calculated start and end times:
ActiveTime.new(2008).starting             # => Tue Jan 01 00:00:00 UTC 2008
ActiveTime.new(2008).ending               # => Wed Dec 31 23:59:59 UTC 2008

# Get a description of the range
ActiveTime.new(2008)                      # => in 2008
ActiveTime.new(2008, 11)                  # => in November 2008
ActiveTime.new(2008, 11, 18)              # => on November 18 2008
ActiveTime.new(2008, 11, 18, 14)          # => from 14:00 to 15:00 on November 18 2008
ActiveTime.new(2008, 11, 18, 14, 18)      # => from 14:18 to 14:19 on November 18 2008
ActiveTime.new(2008, 11, 18, 14, 18, 22)  # => from 14:18:22 to 14:19:23 on November 18 2008

Status

I wrote it and published it to Github in a few hours, so it’s really really fresh and not battle tested at all. Working on it!

Next

  • tests!
  • tidy up the code a bit
  • generate and publish the rdoc
  • support hour, minute and second
  • provide Day, Year and Month wrapper classes
  • anything
  • parse more date formats for input
  • figure out if I need to care about time zones (everything assumes UTC right now)
  • figure out if I care about localization
  • figure out if I can replace the method_missing magic with something more declarative

Project Info

ActiveTime is hosted on Github, where your contributions, forkings, comments and feedback are greatly welcomed.

Copyright © 2008 Justin French, released under the MIT license.

Something went wrong with that request. Please try again.