【Rails】コントローラコールバックによる変数の初期化について
はじめに
初めまして!現在プログラミング学習中のるやんと申します。
学習中にコントローラコールバックの呼び出しタイミングに疑問を感じたため、実験して挙動を確認しました。その内容をまとめます。
概要
プログラミングの学習中に、とあるプログラムのApplicationControllerにて、変数@hogehoge
を初期化するコントローラコールバックbefore_action :init_hogehoge
の記述を見つけました。
これを見て、「ApplicationControllerが呼び出される度に毎回@hogehoge
は初期化されてしまうのではないか?」と疑問に思い、挙動を確認することにしました。
対象読者
- Ruby on Rails初学者の方
- コントローラコールバックの動作について学びたい方
コントローラコールバックとは
コントローラコールバックとは、コントローラのアクションが実行される、直前、直後などに実行されるメソッドです。
よく使用されるのが before_action
になるかと思います。
なお、コントローラコールバックは、Railsのバージョンアップに伴いその名前が変わってきたようです。
- ~Rails 7.1 …フィルタ
- Rails 7.2 … アクションコールバック
- Rails 8.0 …コントローラコールバック
本記事では、最新であるコントローラコールバックで統一して表現しています。
筆者環境
以下の環境にて、動作させています。
- Docker環境
- Windows11
- Rails 7.0.3.1
- ruby 3.1.4
疑問
コントローラコールバック before_action
は、ApplicationControllerのメソッドを呼び出すたびに毎回実行されるのではないか?
結論
コントローラコールバックは、1つのリクエストの中でアクションが呼び出された際にのみ動作する
実験
以下のコントローラ・ビューファイルを用意して、hoge#fugaアクションを実行しました。
-
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base before_action :init_test def add_1 @test += 1 end def add_2 @test += 2 end def add_3 @test += 3 end private def init_test @test = 0 end end
-
app/controllers/hoge_controller.rb
class HogesController < ApplicationController def fuga @test = -1 add_1 add_2 add_3 end end
-
app/views/hoges/fuga.html.erb
<%= @test %>
結果
画面には「5」が出力される
考察
デバッガでhoges#fugaが呼ばれた際の流れを追いました。
- まず、
fuga
アクションの前にinit_test
メソッドが実行される。
(ApplicationControllerにコントローラコールバックを記載しているため、ApplicationControllerを継承しているHogesControllerでも実行される)-
before_action :init_test
のコントローラコールバックを実行-
init_test
を実行⇒@test=0
-
-
- 次にHogesControllerの
fuga
アクションが実行される-
@test = -1
を実行⇒@test = -1
で上書き - add_1メソッド実行
-
before_action
は実行されない -
add_1
メソッド実行…+1する⇒@test = 0
-
- add_2メソッド実行
-
before_action
は実行されない -
add_2
メソッド実行…+2する⇒@test = 2
-
- add_3メソッド実行
-
before_action
は実行されない -
add_3
メソッド実行…+3する⇒@test = 5
-
-
fuga.html.erb
に@test = 5
が渡される
-
まとめ
コントローラコールバックはメソッドが呼び出される度に実行される訳では無く、アクションが呼び出された際にのみ実行されることが分かりました。
この特性を利用して、before_action :init_test
にて、変数@test
を初期化することができ、かつinit_test
メソッドで何度も上書きされないことを学びました。
この記事が、皆様のお役に立てれば幸いです。
Discussion