LoginSignup
9
10

More than 3 years have passed since last update.

[Rails] ActiveRecordでデータを更新したときに、各カラムが更新されたかどうか知りたかったんだ

Posted at

はじめに

タイトル通りです。

下のアプリはチャットルームに「タイトル」と「ルームの説明」、「カテゴリ」を設定できるんだけれども、
「タイトル」が変更された時だけトークルームに通知が来るようにしたかった。
Image from Gyazo

変更前のパラメーターを取得するか、変更されたかどうかを判定するメソッドがあったら嬉しいなーと思って探した。

実装

どうやらActiveRecordさんには「カラム名_changed?」っていうヘルパーメソッドがあるらしいと聞いて...

room_controller
  def update
    if @room.update(room_update_params)
      if @room.title_changed? # ココ。title_cahged?がtrueであれば自動メッセージを送るようにしたつもり。
        Message.create(room_id: @room.id, user_id: current_user.id, content: "*自動投稿* タイトルを「#{@room.title}」に編集しました")
      end
      redirect_to room_path(@room.id)
    else
      render :edit
    end
  end

こんな感じで実装してみたのだけれども失敗した。

Githubのrailsを見てみると、なんか更新されているらしい。

つまり

カラム名_changed?は、ActiveRecordのコールバックを使って処理を分けることができていたが、

コールバックまとめ

save前の場合は、

オブジェクト.will_save_change_to_カラム名

save後の場合は、

オブジェクト.saved_change_to_{カラム名}?

という風に書き変える必要があるみたい。

再度実装

room_controller.rb
  def update
    if @room.update(room_update_params)
      if @room.title_updated?
        Message.create(room_id: @room.id, user_id: current_user.id, content: "*自動投稿* タイトルを「#{@room.title}」に編集しました")
      end
      redirect_to room_path(@room.id)
    else
      render :edit
    end
  end

コントローラーで「saved_change_to」やら「will_save_change_to」やらを呼び出すとうまくいかなかったので、
モデル側に「更新されたかどうか判別するインスタンスメソッド」を作りました。

room.rb
  def title_updated?
    if self.saved_change_to_title?
      return true
    else
      return false
    end
  end

これでタイトル編集時のみメッセージが投稿されるようになりました。

Image from Gyazo

おわりに

今回初めてrailsのソースコードを見ましたが、もっと見ていくととても勉強になりそうです。
暇を見つけてもっと読んでみようと思いました。

おわり。

9
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
10