Ruby on Rails
ExtendingActiveRecordExample (Version #7)

_blatantly copied from this email by JeremyKemper on the mailing list _

Timestamping callbacks are set up by default for columns named created_at/created_on and updated_at/updated_on. See http://rails.rubyonrails.com/classes/ActiveRecord/Timestamp.html

Using callbacks

Callbacks let you set up “triggers” like this easily. You can reimplement timestamping yourself:


class Foo < ActiveRecord::Base
  before_create { |foo| foo.created_at = Time.now }
  before_save   { |foo| foo.updated_at = Time.now }
end

Package it in a module

Wonderful! Now say we want timestamps in our other models. Let’s make a module to mix in the behavior:


module Timestamped
  # Invoked when "include Timestamped" is called in base_class.
  def self.append_features(base_class)
    base_class.before_create { |model| model.created_at = Time.now }
    base_class.before_save   { |model| model.updated_at = Time.now }
  end
end

It can now be mixed in to a model.


class Foo < ActiveRecord::Base
  include Timestamped
end

Make it generic

Then say this is so useful we’d like to add it to any models with these columns:

/lib/timestamped.rb


module Timestamped
  def self.append_features(base)
    base.before_create do |model|
      model.created_at ||= Time.now if model.respond_to?(:created_at)
    end
    base.before_save do |model|
      model.updated_at = Time.now if model.respond_to?(:updated_at)
    end
  end
end

Extend ActiveRecord, which extends all of your models with this module.

in /config/environment.rb


require 'timestamped'
class ActiveRecord::Base
  include Timestamped
end

See UnderstandingWhatMethodsGoWhere for further discussion about where these methods/modules could be placed.

category: Example

_blatantly copied from this email by JeremyKemper on the mailing list _

Timestamping callbacks are set up by default for columns named created_at/created_on and updated_at/updated_on. See http://rails.rubyonrails.com/classes/ActiveRecord/Timestamp.html

Using callbacks

Callbacks let you set up “triggers” like this easily. You can reimplement timestamping yourself:


class Foo < ActiveRecord::Base
  before_create { |foo| foo.created_at = Time.now }
  before_save   { |foo| foo.updated_at = Time.now }
end

Package it in a module

Wonderful! Now say we want timestamps in our other models. Let’s make a module to mix in the behavior:


module Timestamped
  # Invoked when "include Timestamped" is called in base_class.
  def self.append_features(base_class)
    base_class.before_create { |model| model.created_at = Time.now }
    base_class.before_save   { |model| model.updated_at = Time.now }
  end
end

It can now be mixed in to a model.


class Foo < ActiveRecord::Base
  include Timestamped
end

Make it generic

Then say this is so useful we’d like to add it to any models with these columns:

/lib/timestamped.rb


module Timestamped
  def self.append_features(base)
    base.before_create do |model|
      model.created_at ||= Time.now if model.respond_to?(:created_at)
    end
    base.before_save do |model|
      model.updated_at = Time.now if model.respond_to?(:updated_at)
    end
  end
end

Extend ActiveRecord, which extends all of your models with this module.

in /config/environment.rb


require 'timestamped'
class ActiveRecord::Base
  include Timestamped
end

See UnderstandingWhatMethodsGoWhere for further discussion about where these methods/modules could be placed.

category: Example