ActsAsEventOwner is an ActiveRecord extension that adds calendar event management to any ActiveRecord model. Models that declare themselves as acts_as_event_owner gain two has_many associations- one for the event specifications, and one for the event occurrences.

ActsAsEventOwner supports recurring events, with roughly the same recurrence rule capabilities as Apple’s iCal application. Under the hood, ActsAsEventOwner uses ri_cal to provide recurring event support.


Rails 2.3.x

ActsAsEventOwner is available both as a gem and as a plugin.

Installing as a Rails 2.3.x plugin

To install as a plugin, just do

  script/plugin install git://

You’ll also need to install the ri_cal gem by the method of your choice (bundler, system gems, etc).

Installing as a Rails 2.3.x gem

To install as a gem, use your preferred method of gem installation, e.g. Bundler, config.gem, etc.

Rails 2.3.x post-installation steps

After installation, generate a migration to add ActsAsEventOwner tables to your database:

  script/generate acts_as_event_owner_migration
  rake db:migrate

If you want to use the acts_as_event_owner rake tasks, put the following in your Rakefile:

  if Gem.searcher.find('acts_as_event_owner')
    Dir["#{Gem.searcher.find('acts_as_event_owner').full_gem_path}/**/tasks/*.rake"].each { |ext| load ext }

Rails 3

Just add it to your Gemfile, like so:

  gem 'acts_as_event_owner'

Then do:

  bundle install

Rails 3 post-installation steps

After installation, generate a migration to add ActsAsEventOwner tables to your database:

  rails generate acts_as_event_owner:migration
  rake db:migrate


  class User < ActiveRecord::Base

  @user = User.create :name => 'Alvin Seville'
  @user.event_specifications.create :description => 'acquire cheese balls',
    :start_at =>,
    :repeat => :daily,
    :generate => false # => [] :from =>, :to => + 1.week

  # override the description on a per-generate basis :from => -, :to => + 1.week,
    :attributes => { :description => 'acquire cheese balls, like, right away!' } # => (8 ActsAsEventOwner::EventOccurrence objects) # => (1 ActsAsEventOwner::EventOccurrence objects) #=> (7 ActsAsEventOwner::EventOccurrence objects)

Adding custom fields

You can create your own migrations to add custom fields to the event objects- just make sure that you add the same fields to both the event_specifications and event_occurrences tables.

When you create an EventSpecification, set the value of your custom fields, then, later, when you call generate, the values of those fields in the EventSpecification will be copied over to any generated EventOcurrence records.

Just like you can do with the standard :description attribute, you can override the default value of your custom fields with the :attributes parameter when you call generate.

Recurrence rules

ActsAsEventOwner supports recurrence rules roughly equivalent to those supported by Apple’s iCal application. Examples are:

One-time event

  EventSpecification.create :description => 'pick up laundry',
    :start_at => Time.parse("4:00pm")

Every day at 08:00, 13:00, and 18:00

  EventSpecification.create :description => 'walk the dog',
    :start_at => Time.parse("8:00am"),
    :repeat => :per_hour,
    :target => [8,13,18]

Every day

  EventSpecification.create :description => 'eat breakfast',
    :start_at => Time.parse("7:30am"),
    :repeat => :daily

Every three days

  EventSpecification.create :description => 'call mom',
    :start_at => Time.parse("10:30am"),
    :repeat => :daily,
    :frequency => 3

On Monday, Wednesday, and Friday of each week

  EventSpecification.create :description => 'go to the gym',
    :start_at => Time.parse("6:30am"),
    :repeat => :weekly,
    :on => [ :mo, :we, :fr ]

On Thursday, every other week

  EventSpecification.create :description => 'clean the bathroom',
    :start_at => Time.parse("8:00pm"),
    :repeat => :weekly,
    :frequency => 2, :on => [ :th ]

On the 10th and 25th of each month

  EventSpecification.create :description => 'pick up paycheck',
    :start_at => Time.parse("9:30am"),
    :repeat => :monthly,
    :on => [ 10, 25 ]

On the last Saturday of each month

  EventSpecification.create :description => 'run a marathon',
    :start_at => Time.parse("6:30am"),
    :repeat => :monthly,
    :on_the => :last,
    :target => [ :sa ]

On the last weekday of each month

  EventSpecification.create :description => 'wine tasting',
    :start_at => Time.parse("6:30pm"),
    :repeat => :monthly,
    :on_the => :last,
    :target => :wkday

Every April 15th

  EventSpecification.create :description => 'pay taxes',
    :start_at => Time.parse("4/15/2010 5:00pm"),
    :repeat => :yearly

On the second Thursday in May, every other year, until Dec 31, 2012

  EventSpecification.create :description => 'freak out',
    :start_at =>,
    :repeat => :yearly,
    :frequency => 2,
    :on => [ 5 ],
    :on_the => :second,
    :target => [ :th ],
    :until => Time.parse("12/31/2012")

Using the Rake task

A rake task is included to generate occurrences of recurring events. For example, you might run this out of a cron job each day to generate any recurring events for the next 30 days, or whatever.

  rake acts_as_event_owner:generate_events FROM=9/1/2010 TO=10/1/2010


ActsAsEventOwner was developed for Josh Pigford and Sabotage Media LLC, for use in their excellent Critterly product. Big thanks to Josh and Sabotage for agreeing to make ActsAsEventOwner available by open source!