特定のカラムの更新日を管理するためのGemを作りました

self_updated_atという、ActiveRecordで指定したカラムに対して更新が発生したときに更新日時を書き換えるgemを作りました。

利用方法

ActiveRecordのModelに以下のように設定します。 下記のように設定すると、titleとbodyの内容に変更があったときのみ、service_updated_atの時間が更新されるというような具合です。

class Post < ActiveRecord::Base
  self_updated_at :service_updated_at, columns: [:title, :body]
end

Gemを作った背景

業務やビジネス要件によって振る舞いを変更する「更新日」処理を簡単にするため

業務やビジネス要件によって振る舞いを変更したい「更新日」に対してActiveRecordが利用する updated_atは利用するべきではないと考えています。 なぜなら、「特定のカラムを更新したときにupdated_atは更新しない」を実現するのが現実的ではないと思っているからです。

例えば、updated_atを更新しないで特定のカラムを更新する方法として、update_columnというメソッドがActiveRecordにもありますが、確実に漏れると思っています。 誰かが運悪くupdateと書いてデータが更新されてしまった瞬間にupdated_atは更新されてしまい、今まで苦労は水泡に帰してしまいます。

そうならないために別のカラムを用意して、それを「サービスとしての更新日」として実装・利用するほうが良い思ったからです。*1

ただ、なんかスマートじゃないしカラム名だけ指定すればOKみたいに作れれば良いなぁ...というのが大きなモチベーションです。

どうしてupdated_atを直接改変しないのか

フレームワークで自動で更新されることがレールで敷かれており、業務やビジネス要件によって振る舞いを変更したい「サービスとしての更新日」に対して利用するべきではないと考えています。 それがフレームワークのデフォルトの振る舞いなので、そこを変に改変しないほうが良いと思っているからです。*2

TODO

  • ひとまずv0.0.1として出したけど、簡単なGemと言いつつもテストをまだ書けていない。さっさとテストを書く。
  • このブログを書いてて思ったのは、hooks_columnsという記法が微妙なので、columnsへの変更。
  • シンプルはシンプルだけど、READMEもちゃんと書く
  • 今はModelのカラムが更新されているかという条件しか指定出来ないので、さらにメソッド名かLambdaを渡せるオプションがあればうれしいですね
    • この当たりができればv1.0.0としてシュッとリリースしたい。

最後に

このGemを使うか使わないかは置いておいて、updated_atを「ビジネス・仕様上の更新日」として利用する場合は、ActiveRecordが更新するupdated_atとは別のカラムで管理したほうが幸せになれる。ということを強く言いたい。

あと、もし類似するライブラリがあったら教えてください... 簡単に探してみたけどなさそうだったのでサクッと作ってしまったので...

*1:このあたりの実装で、自分が痛い目を見たというのは内緒...

*2:このModelのupdated_atは「xxxx」カラムが更新されてもupdated_atは更新されないように注意してね...というのがあったりするのはまずいと思っている。