Controllerのbefore_actionにおける インスタンス変数セットについて
Transcript of Controllerのbefore_actionにおける インスタンス変数セットについて
Controllerのbefore_actionにおけるインスタンス変数セットについて
自己紹介名前 : pospomeブログ : http://d.hatena.ne.jp/pospome/職種 : サーバサイドエンジニアrails歴:2 ~ 3ヶ月
before_actionでインスタンス変数をセットしているコードを
見かけることがある
class UserController < ApplicationController before_action :set_user def index() //何らかの処理 @user.execute end private def set_user @user = User.findby(id: 100) endend
before_action で変数をセットする実装が好きではない
自分ならこう書く
class UserController < ApplicationController def index() @user = find_user(100) @user.execute end private def find_user(id) User.findby(id: id) endend
before_actionでの変数セットをやめてaction側でprivateな関数を呼び出す
サーバサイドでjsonを返す場合はインスタンス変数すら不要になるので、
user変数のスコープを狭くできる
class UserController < ApplicationController def index() user = find_user(100) user.execute render json: user end private def find_user(id) User.findby(id: id) endend
なぜ、こういった実装をするのか?
before_actionが連続した場合の変数書き換えを防ぐ
class UserController < ApplicationController // それぞれで同じ変数を書き換えているかも // before_action が増えたら、 // 実行順と変数の状態を考慮する必要がある before_action :aaa before_action :bbb, only: ['index', 'detail'] before_action :ccc, except: ['index', 'detail']end
before_actionは戻り値を取れないので、Controller内のインスタンス変数に対して副作用を与える実装になってしまいがちaction内で明示的に呼ぶことによって
参照透過な実装になる
データの読み込みも処理の一部action内で明示することによって、処理の流れがaction内で完結する
before_actionは何をするのか?
actionを実行するかどうかのバリデーションに利用する
例:権限チェック
可能な限りbefore_action同士で依存関係を
持たないようにした方がいい
人によってはDRYに反していると思うかもしれないが、action内の関数呼び出しは重複だろうか?
変数のスコープを限定する方が大事だと思う
同じ考えを持つ方々http://craftingruby.com/posts/2015/05/31/dont-use-before-action-to-load-data.htmlhttp://blog.ragnarson.com/2015/09/30/problems-with-typical-rails-controllers-and-before-actions.htmlhttp://blog.thefrontiergroup.com.au/2014/02/before_action
_an_anti_pattern/
「Best Practice」らしいが、コメント欄を確認すると面白い
http://rails-bestpractices.com/posts/2010/07/24/use-
before_filter/
今回の内容はrailsというよりも変数のスコープや副作用の話なので、
実はrails関係ない
おわり
ここから発表後の追記です
発表時間が余ったので
before_actionで変数をセットしている人いますか?
と聞いたところ・・・・
25人中2,3人がセットしているとのこと
before_actionで変数セットするのって少数派なのかな・・・
だとしたら、わざわざ取り上げるテーマでもなかった
かもしれない・・・