kiyo_hikoのブログ

メモ+日記?

ActiveRecordでDB更新したらログ吐かせたい

データの変更とか追いたいから、モデルがsaveされる(DBが更新される)ごとにログ吐くようにする。

以下2手順にて実現

1.モデルの共通的なベースを作る(前準備)
2.ベースのafter_saveフック内でログを吐かせる(やりたかったこと)

もっといい方法あるかもし、このやり方がうまげって保証無し。

手順1.モデルの共通的なベースを作る(前準備)

まずモデルにアプリ内で共通的に使う拡張機能を付ける。
このやり口はやっとくと便利な取り組みだと思ってる。開発とか数件しかしたこと無いけど。

ここでやることは2種類

concernという仕組み使ったモジュールを書き、これをアプリの標準的なモデルに取込ませる。

やること1.concern例:

共通の機能はActiveSupport::Concernを継承したモジュール書いてそれにメソッドとか定義。

models/concerns/regular_model.rb

# このアプリの共通的なモデル拡張
module RegularModel extend ActiveSupport::Concern
  def common_method
    # 何か共通的な処理
  end
end
やること2.model側の取込み例

modelのコードに以下の「これ」を追加。→ concernで定義した機能をmodelが持つ!

class Unko < ActiveRecord::Base
  # ↓これ
  include RegularModel
end

手順2.ベースのafter_saveフック内でログを吐かせる(やりたかったこと)

先にコード例。そのあと補足1点。

models/concerns/regular_model.rb

# このアプリの共通的なモデル拡張
module RegularModel extend ActiveSupport::Concern
  included do
    after_save :after_save_log
  end

  def after_save_log
    logger.warn "#{Time.now.localtime.strftime('%H:%M:%S')}#{self.class.name}が更新されました。" # ← ログ出力
    self
  end
end
補足1.includedてなんなの

ペラペラのモデルにフック書くなら

after_save :method_name # メソッド名シンボルを書く

でいいはずなのだけども、この方式はそのままconcernには持ち込めない。
includedで囲ってやる必要がある。

ruby on rails - Is it possible to define a 'before_save' callback in a module? - Stack Overflow

included do
  after_save :method_name
end