Roobie Nuby
Roobie Nuby

Reputation: 1439

How to keep history in rails model

There are three questions here, all of them set in bold.

I have a personnel database where historical data is also stored. Each table has two columns start and stop which indicate the period during which this fact is valid.

When any field of a record changes, a new record is created with start=today, and stop=nil, and the old record is given a stop=today-1 (or whatever the effective date of the change is instead of today).

When a record is to be deleted, instead of deleting, we simply set stop=today.

This way, it is easy to

Firstly this pattern seems common enough that probably I should not need to re-invent the wheel. Yet in my search all I found were some gems called auditable or papertrail. From a first glance, they did not seem to do what I want, but perhaps I am mistaken. Do you know of a gem that does something similar?

If I don't find a solution, what is enough for my purposes is to have a few methods which works for all my models, like

def when(date)
    self.where("start <= ? and ? <= stop", ondate, ondate)
end

I thought about inheriting

class MyRecord < ActiveRecord::Base
    def when ...
    end
end

and having all my models inherit from MyRecord, but this broke everything. Why?

I could just add my methods to ActiveRecord::Base, but that seems wrong. What is the proper way to add a method to all models?

Answer

Parts 2 and 3 of this question have been answered before here. Since that contains Josh's answer (which I +1ed), as well as why inheriting from MyRecord doesn't work, I did not accept Josh's answer.

I still have not located a gem which maintains a good history, but two out of three ain't bad...

Upvotes: 1

Views: 1193

Answers (1)

Josh
Josh

Reputation: 5721

This sounds to me like an excellent opportunity to use an ActiveSupport::Concern. You could write something like:

History.rb

require 'active_support/concern'

module History
  extend ActiveSupport::Concern
  included do
    def self.when(date)
      self.where("start <= ? and ? <= stop", ondate, ondate)
    end
  end
end

Your model

class SomeClass < ActiveRecord::Base
  include History
end

You could then call SomeClass.when(some_date_string) on any models that you need to include history on.

Upvotes: 1

Related Questions