Upgrade to Pro — share decks privately, control downloads, hide ads and more …

before action setter いる? / Good-bye "before action setter"

OSA Shunsuke
September 06, 2018

before action setter いる? / Good-bye "before action setter"

表参道.rb #38 〜Railsアンチパターン〜 でやった LT です。
https://omotesandorb.connpass.com/event/98377/

元ネタ: http://osa.hatenablog.com/entry/good-bye-before-action-setter

OSA Shunsuke

September 06, 2018
Tweet

More Decks by OSA Shunsuke

Other Decks in Programming

Transcript

  1. before action setter いる?
    2018-09-06 表参道.rb #38
    1

    View Slide

  2. 自己紹介
    • @s_osa_
    • OSA Shunsuke
    • Cookpad Inc.
    • 技術部 ユーザー・決済基盤グループ
    • Rails に対しては愛憎相半ばする複雑な気持ちを抱い
    ている
    2

    View Slide

  3. 話すこと
    • before action setter って必要?
    • 多くの場合、いらないのでは?
    3

    View Slide

  4. before action setter
    名前がないといろいろ不便なので、勝手に before action
    setter と呼んでいますが、要は scaffold でも生成されるこいつ。
    class HogesController < ApplicationController
    before_action :set_hoge, only: %i[show]
    private
    def set_hoge
    @hoge = Hoge.find(params[:id])
    end
    end
    4

    View Slide

  5. つらい理由
    5

    View Slide

  6. 変数の初期化・代入を目的としたメソッド
    set_* を呼ぶと、メソッド呼び出し側にインスタンス変数
    が増えるという重大かつ直感的でないな副作用がある。
    普段コードを書くときに
    def set_message
    @message = 'Hello'
    end
    set_message
    みたいなことをする人はまずいないはず。
    6

    View Slide

  7. 自明でない順序依存性が発生しがち
    はじめはシンプルだった before action setter も、機能
    追加などをしていくうちに、いつの間にか
    before_action :set_hoge
    before_action :set_fuga
    before_action :set_foo # set_bar ΑΓઌʹ࣮ߦ͢Δ͜ͱʂʂ
    before_action :set_bar
    のようなことになりがち。
    7

    View Slide

  8. action の関心がわかりにくい
    Rails の controller におけるインスタンス変数は view で
    参照する変数であり、レスポンスを組み立てるために必要
    なものが入っている。
    インスタンス変数が暗黙的に代入されると、その action
    の関心が何なのかが少なくともパッとはわからない。
    8

    View Slide

  9. じゃあ、どう書くか
    9

    View Slide

  10. シンプルなとき
    そのまま書けば良い。
    class HogesController < ApplicationController
    def show
    @hoge = Hoge.find(params[:id])
    end
    def edit
    @hoge = Hoge.find(params[:id])
    end
    # ...
    end
    10

    View Slide

  11. 複雑・重要な絞り込みがあるとき
    具体的には、複雑だったり重要だったりする絞り込みを行なっていて、その重複を避けたい場合。
    そういうときは set_* じゃなく find_* する。
    class HogesController < ApplicationController
    def show
    @hoge = find_hoge(params[:id])
    end
    private
    # @param id [String]
    # @return [Hoge]
    def find_hoge(id)
    Hoge.very.complex.condtion.find(id)
    end
    end
    11

    View Slide

  12. 順序依存性があるとき
    複数の before action setter の間に順序依存性があったケースでは依存を明確にして管理するために引数として渡す。
    class HogesController < ApplicationController
    def show
    @hoge = find_hoge(params[:id])
    @fuga = find_fuga(@hoge)
    end
    private
    # @param id [String]
    # @return [Hoge]
    def find_hoge(id)
    Hoge.very.complex.condtion.find(id)
    end
    # @param hoge [Hoge]
    # @return [Fuga]
    def find_fuga(hoge)
    hoge.fugas.very.important.condition.first
    end
    end
    12

    View Slide

  13. before action を使うべきとき
    13

    View Slide

  14. 認証・検証など
    • action が呼ばれる際に満たしておく事前条件のようなものが存
    在し、その条件を満たさないときは action を実行しないような
    類のもの。
    •authenticate_*! とか verify_*! みたいなメソッド名が
    多い。
    • 別の言い方をすると、before_action の旧名である
    before_filter という名前がしっくり来る感じのやつ。
    •setter じゃないことも多いが、認証・検証後に set することもあ
    りがち。
    14

    View Slide

  15. 横断的に使用される変数など
    • 典型的には set_current_user のようなもの。
    • そのアプリケーションで横断的に使われる変数などの初期
    化・代入。
    •広く使われるものであれば、そのアプリケーションを開発
    する人の基礎知識とすることに妥当性が生まれる。
    • 横断的に使用されるという性質上、この種の before action
    setter は ApplicationController や
    Admin::BaseController のような場所に定義される。
    15

    View Slide

  16. まとめ
    16

    View Slide

  17. まとめ
    • before action setter って必要?
    • 多くの場合、いらない。
    • Rails とはいい感じに折り合いをつけて付き合っていきた
    い。
    17

    View Slide

  18. Thank You!
    18

    View Slide