ActiveRecord::Events Gem version Build status Coverage status Maintainability status

An ActiveRecord extension providing convenience methods for timestamp management.


Watch screencast (courtesy of Mike Rogers)


Add the following line to your application's Gemfile:

gem 'active_record-events'

Install the gem with Bundler:

$ bundle install

Or do it manually by running:

$ gem install active_record-events


Recording a timestamp in order to mark that an event occurred to an object is a common practice when dealing with ActiveRecord models. A good example of such an approach is how ActiveRecord handles the created_at and updated_at fields. This gem allows you to manage custom timestamp fields in the exact same manner.


Consider a Task model with a completed_at field and the following methods:

class Task < ActiveRecord::Base
  def completed?

  def not_completed?

  def complete
    complete! if not_completed?

  def complete!

  def self.complete_all

Instead of defining all of these methods by hand, you can use the has_event macro provided by the gem.

class Task < ActiveRecord::Base
  has_event :complete

As a result, the methods will be generated automatically.

It's important to note that the completed_at column has to already exist in the database. Consider using the generator to create a necessary migration.


In addition, the macro defines two scope methods – one for retrieving objects with a recorded timestamp and one for those without it, for example:

scope :not_completed, -> { where(completed_at: nil) }
scope :completed, -> { where.not(completed_at: nil) }

The inclusion of scope methods can be omitted by passing the skip_scopes flag.

has_event :complete, skip_scopes: true

Multiple events

Using the macro is efficient when more than one field has to be handled that way. In such a case, many lines of code can be replaced with an expressive one-liner.

has_events :complete, :archive

Date fields

In case of date fields, which by convention have names ending with _on instead of _at (e.g. completed_on), the field_type option needs to be passed to the macro:

has_event :complete, field_type: :date

Custom field name

If there's a field with a name that doesn't follow the naming convention (i.e. does not end with _at or _on), you can pass it as the field_name option.

has_event :complete, field_name: :completion_time

Note that the field_name option takes precedence over the field_type option.

Specifying an object

There are events which do not relate to a model itself but to one of its attributes – take the User model with the email_confirmed_at field as an example. In order to keep method names grammatically correct, you can specify an object using the object option.

class User < ActiveRecord::Base
  has_event :confirm, object: :email

This will generate the following methods:

  • email_not_confirmed?
  • email_confirmed?
  • confirm_email
  • confirm_email!
  • confirm_all_emails (class method)

As well as these two scopes:

  • email_confirmed
  • email_not_confirmed

Using a Rails generator

If you want to quickly add a new event, you can make use of a Rails generator provided by the gem:

$ rails generate active_record:event task complete

It will create a necessary migration and insert a has_event statement into the model class.

# db/migrate/XXX_add_completed_at_to_tasks.rb

class AddCompletedAtToTasks < ActiveRecord::Migration[6.0]
  def change
    add_column :tasks, :completed_at, :datetime
# app/models/task.rb

class Task < ActiveRecord::Base
  has_event :complete

All of the macro options are supported by the generator and can be passed via the command line. For instance:

$ rails generate active_record:event user confirm --object=email --skip-scopes

For more information, run the generator with the --help option.

Overriding methods

If there's a need to override any of the methods generated by the macro, you can define a new method with the same name in the corresponding model class. This applies to instance methods as well as class methods. In both cases, the super keyword invokes the original method.

class Task < ActiveRecord::Base
  has_event :complete

  def complete!
    super"Task #{id} has been completed")

  def self.complete_all
    super'All tasks have been completed')


See also