Hanami::Controllerで共通の処理を差し込む

Meetup #100 - Kanazawarb に参加したらちょっと高まったので!

Hanamiは比較的継承が少ない

Hanami のコードの一つの特徴として、「継承を避けて mixin を使いがち」というものがある。もう少し具体的には

パス実現方法
apps/Action も View も moulde の mixin
lib/Hanami::Entity も Hanami::Repository も継承
lib/*/mailers/mixin
db/migrations/単なる DSL

のようになっていて、簡単に言うと Rails のようには

ApplicationController にメソッドを追加したらすべての controller で使える、みたいな素朴な OOP が通用しない

ようになっている。

これはこれで巨大な superclass を作らないようにさせる矯正ギプスとして面白いなと思う反面、mixin が多くなるのは Ruby 力を要求しやすいのでは? という気もしないでもない。

ApplicationControllerの代わりになるもの

application.rb の中の

module Web
  class Application < Hanami::Application
    configure do
      ..
      # Handle exceptions with HTTP statuses (true) or don't catch them (false).
      # Defaults to true.
      # See: http://www.rubydoc.info/gems/hanami-controller/#Exceptions_management
      #
      # handle_exceptions true

      controller.prepare do
        # include MyAuthentication # included in all the actions
        # before :authenticate!    # run an authentication before callback
      end
    end
  end
end

ここ。

Controllerのbefore, after callback

Actions: Control Flow | Hanami Guides

Controller には before / after の callback があって、Symbol を使ってメソッドを呼んだり、直接 block を与えたりすることができる。これは Rails の Controller によく似ていて、この before / after メソッドを 上の controller.prepare block にも与えることができる。

もし ApplicationController の before / after で処理を加えていたのなら、ここに同じように書くことができる。

configure do
  controller.prepare do
    before do
      ..
    end
  end
end

また、この中で self を参照すると実際に request を受けた Controller を取得できる。

例外を拾う

例外を拾う方法は以下のようになっている。

フレームワーク例外を処理するメソッド
Railsrescue_from
Hanamihandle_exception

Rails の ApplicationController で言う rescue_from は Hanami では handle_exception になるんだけど、これも上の before / after と同じように Action に該当する class 内に書いても controller.prepare に与える block 内に書いても同じように動作する。

ただし、development では handle_excepions が false になっているので、

  configure :development do
-   handle_exceptions false
+   handle_exceptions true
  end

に変更しておかないと実際のエラーを目視しながら開発することはできない。これも Rails と同じだと思う。

More