Rails の touch 時に処理をフックする

任意のレコードの updated_at のみを更新する際に ActiveRecord#touch を使うことはあると思います。

class User < ActiveRecord::Base
end

user = User.create(name: "Homu")

pp user.updated_at.iso8601(10)
# => "2019-02-18T12:36:37.2315494900Z"

# updated_at のみを更新する
user.touch

pp user.updated_at.iso8601(10)
# => "2019-02-18T12:36:37.2315494900Z"

#touch 時に処理をフックする

#touch がやっていることは『updated_at の更新』なので after_save 等でフックしたくなるんですが残念ながら #touch 時には after_save は呼ばれません。

class User < ActiveRecord::Base
    # #touch 時に after_save は呼ばれない
    after_save {
        pp "after_save"
    }
end

#touch 時に処理をフックする場合は after_touch を使用します。

class User < ActiveRecord::Base
    # touch で更新した後に after_touch が呼ばれる
    after_touch {
        pp "after_save"
        pp updated_at.iso8601(10)
    }
end

user = User.create(name: "Homu")

pp user.updated_at.iso8601(10)

user.touch

pp user.updated_at.iso8601(10)
# output:
# "2019-02-18T12:40:49.6699328380Z"
# "after_save"
# "2019-02-18T12:40:49.6741588740Z"
# "2019-02-18T12:40:49.6741588740Z"

#touch がやっていることは更新なので after_save が呼ばれて当然と思っていてハマりました。 #touch 時には、

  • after_touch
  • after_commit
  • after_rollback

のみが呼ばれます。