コンテンツにスキップ

rigor-hanami

Hanami 3.xアプリに対してHanami::Actionプロトコルを強制します。app/actions/**/*.rb配下のすべてのクラスは#handle(request, response)を定義しなければならず(MUST)、それらの本体の内部でRigorは2つのパラメータをそれぞれHanami::Action::Request / Hanami::Action::Responseとして型付けするため、誤用が的確に捕捉されます。これはADR-28のパススコープのメソッドプロトコル契約(contract)のリファレンス実装としてのプロダクション利用者です ── Rigorがパラメータ型を提供し、プラグインがメソッドのシェイプ(shape)を検査します。ソースのみを読み取り、hanamiランタイム依存を持ちません(Request / Response / Paramsのサーフェス(surface)に対するRBSスタブを同梱しています)。

これはrigortypeにバンドルされて配布されます。plugins:の下で有効化します。

plugins:
- rigor-hanami
app/actions/books/index.rb
module Bookshelf
module Actions
module Books
class Index < Bookshelf::Action
def handle(request, response)
response.status = 200 # response: Hanami::Action::Response
response.body = request.params[:q] # request: Hanami::Action::Request
request.no_such_method # エラー: call.undefined-method
end
end
end
end
end
ルール重大度発火条件
plugin.hanami.missing-handle-methoderrorマッチするファイル内のクラスが#handleを定義していない
plugin.hanami.handle-arity-mismatcherror#handleが2以外のパラメータ数で定義されている

適合する#handleの内部では、request / responseの誤用はエンジン自身のcall.undefined-methodとして顕在化します ── 型がRBSで宣言されていた場合とまったく同じです。戻り値型の適合性は検査されません#handleは契約上voidであり(responseはインプレースで変更される)、戻り値を検査するとあらゆる条件分岐で偽陽性が発生してしまうためです。パラメータ名は任意です(バインドされるのは名前ではなく位置です)。検査されるのは直接定義された#handleのみで、継承されたものは対象外です。

plugins:
- gem: rigor-hanami
config:
action_path: "app/actions/**/*.rb" # デフォルト

カスタムなスライス(slice)レイアウトのためにaction_pathを上書きできます(例: "slices/main/actions/**/*.rb")。この上書きは、パラメータ型の提供と#handleの検査の両方を再ターゲットします。

  • 厳密なアリティ(arity)#handleはちょうど2つのパラメータを取らなければなりません。オプショナルまたはキーワード専用の形式はhandle-arity-mismatchとしてフラグされます。
  • 直接定義のみ。基底クラスから継承された#handle(クラス自身で定義されたものではない)は検出されません。
  • スタブ化されたサーフェス。バンドルされたRBSはドキュメント化されたRequest / Response / Paramsのメソッドをカバーします。そのサーフェス外への呼び出しは、稼働中のHanamiインストールではなくスタブに対して解決されます。

ProtocolContract宣言、アクションチェッカー、RBSスタブ、ADR-28のprovide-and-check分割については、プラグインのREADMEにあります。プラグインの書き方についてはexamples/rigor-plugin-authorスキルを参照してください。

© 2026 TypedDuck. Licensed under CC BY-SA 4.0.