け〜くんこと K.Ktouth のだらだらした日常と突発的に作るプログラムや読み物とかの雑多サイト
Ramaze の コントローラクラスの公開メソッドはアクションメソッドとして認識されます。
その際、パラメータを指定しておくとURLのパラメータを簡単に取得できます……が、ここにちょっとした落とし穴があることに気づきました。
簡単にまとめると「テンプレートの存在するアクションメソッドに(初期値の存在しない)必須パラメータがある場合、アクションメソッドが呼ばれずにテンプレートだけ適用されてしまう」という現象です。そのため、テンプレート内でアクションメソッド内で初期化されているべきインスタンス変数にアクセスするとエラーを発生させてしまいます。
(以下、詳細説明)
以下のソースは、その現象を再現するためのコントローラです。
class TestController < Ramaze::Controller
engine :Erubis
map '/test'def foo
@data = ['foo', 156]
enddef bar(key = nil)
@data = [key || 'bar', 11849]
enddef baz(key)
@data = [key || 'baz', 782]
enddef bad(key)
@data = [key || 'bad', 123548]
end
end
対応するテンプレートとして以下のものを使っています。
<%= @data.last %>
これを、view/test フォルダ内に、foo.rhtml / bar.rhtml / bad.html の3つの名前で作成しています。baz.rhtml はありません。
結果は以下の通り。
| No. | アドレス | 出力 |
|---|---|---|
| 1 | http://****/test/foo | 156 |
| 2 | http://****/test/foo/no_args | No action found at: "/foo/no_args" |
| 3 | http://****/test/bar | 11849 |
| 4 | http://****/test/bar/no_args | 11849 |
| 5 | http://****/test/baz | No action found at: "/foo/no_args" |
| 6 | http://****/test/baz/no_args | no_args782 |
| 7 | http://****/test/bad | NoMethodError at /test/bad undefined method 'last' for nil:NilClass |
| 8 | http://****/test/bad/no_args | 123548 |
例7、bad メソッドにパラメータ無しでアクセスした場合、例外が発生してしまっています。
# 例6 の出力はメソッドの返値 (['no_args', 782]) がそのまま出力されています。
上記トラブルは、Action クラスのレンダリングの際に、メソッド実行とテンプレート適用が独立して行われているために発生しているものです。
簡単に Action クラスが行っている処理を説明すると……
Action クラスの生成時
Action#render 実行時
となっています。
この際、メソッドとテンプレートは、各々がURLから切り出した「アクション名」と一致するものを検索し、加えてメソッド検索の際にはパラメータの数が一致しているかどうかも確認しています。
つまり、上記例の場合……
| No. | アドレス | メソッド | テンプレート |
|---|---|---|---|
| 1 | http://****/test/foo | TestController#foo | view/test/foo.rhtml |
| 2 | http://****/test/foo/no_args | TestController#foo('no_args') => nil | view/test/foo.rhtml |
| 3 | http://****/test/bar | TestController#bar | view/test/bar.rhtml |
| 4 | http://****/test/bar/no_args | TestController#bar('no_args') | view/test/bar.rhtml |
| 5 | http://****/test/baz | TestController#baz => nil | nil |
| 6 | http://****/test/baz/no_args | TestController#baz('no_args') | nil |
| 7 | http://****/test/bad | TestController#bad => nil | view/test/bad.rhtml |
| 8 | http://****/test/bad/no_args | TestController#bad('no_args') | view/test/bad.rhtml |
例2・5・7 のメソッド探索は赤字のような形で行われますが、最初のソースのように引数の数が一致しません。結果として Action#method には nil が設定されます。
例5・6 のテンプレート探索は、該当するものがないので Action#view には nil が設定されます。
例1・3・4・6・8 に関しては、正しいアクセスに正しくレンダリングした結果を返しています。
例2・5 に関しても、エラーを正しく返しているという点で問題ありません。
ところが例7 、「パラメータが足りず、かつ、テンプレートが存在する時」だけが想定外の挙動を行っているわけです。例2 でも同様のエラーが出るのならわかるのですが……やはりバグ?
対処方法としては、「パラメータが足りない」という状況を作らないようにする、つまり省略値をつけるのが一番手っ取り早いです。上記例だと TestController#baz のように実装し、内部でパラメータチェックを行い、自前でエラー処理を行うと言うことになります。
上記に加えて「該当メソッドが無くても、テンプレートがあればレンダリング可能」という仕様をきちんと把握しておくことは、想定外の挙動を生まないためには重要だと思います。
OVA『バカとテストと召喚獣 〜祭〜』上巻 [Blu-ray]
(メディアファクトリー)
新品 ¥ 4,409
中古 ¥ 3,680
OVA『バカとテストと召喚獣 〜祭〜』下巻 [Blu-ray]
(メディアファクトリー)
新品 ¥ 4,438
中古 ¥ 2,980
生徒会役員共DJCD「アニメ生徒会役員共が全部わかるラジオ、略して全ラ!...
(キングレコード)
新品 ¥ 2,253
中古 ¥ 1,850
WORKING!! 9 初回限定特装版 (SEコミックスプレミアム)
(高津 カリノ)
新品 ¥ 2,896
中古 ¥ 2,835
「声優グランプリ」公認!声優界<雀王>決定戦! <J-1グランプリ> V...
(オムニバス)
新品 ¥ 3,159
中古 ¥ 3,099
デッドライジング 2【CEROレーティング「Z」】
(カプコン)
新品 ¥ 2,740
中古 ¥ 1,014
スプリンターセル コンヴィクション
(ユービーアイ ソフト)
新品 ¥ 2,979
中古 ¥ 1,397
Xbox 360 250GB
(マイクロソフト)
新品 ¥ 34,980
中古 ¥ 25,400
学園黙示録 HIGHSCHOOL OF THE DEAD 7 オリジナル...
(佐藤 大輔)
新品 ¥ 9,800
中古 ¥ 4,797
学園黙示録 HIGHSCHOOL OF THE DEAD SECRET ...
(佐藤 大輔)
中古 ¥ 2,500
ソードアート・オンライン〈5〉ファントム・バレット (電撃文庫)
(川原 礫)
新品 ¥ 578
中古 ¥ 692
RPG W(・∀・)RLD6 ―ろーぷれ・わーるど― (富士見ファンタ...
(吉村 夜)
新品 ¥ 651
中古 ¥ 1
魔法少女リリカルなのはViVid (3)限定版 (角川コミックス・エース...
(藤真 拓哉)
新品 ¥ 1,680
中古 ¥ 1,338
魔法戦記リリカルなのはForce (3)限定版 (角川コミックス・エース...
(緋賀 ゆかり)
新品 ¥ 1,680
中古 ¥ 418
ダンジョンズ&ドラゴンズ第4版スターター・セット
(ジェームズ ワイアット)
新品 ¥ 4,980
中古 ¥ 4,311
アリアンロッド・サガ・リプレイ(5) 激闘のピースメイカー (富士見ド...
(菊池 たけし/F.E.A.R.)
新品 ¥ 693
中古 ¥ 190
アリアンロッド・サガ・コンチェルト 1 (電撃コミックス)
(佐々木 あかね)
新品 ¥ 599
中古 ¥ 90
堀さんと宮村くん(7)(ガンガンコミックスONLINE)
(HERO)
新品 ¥ 1,000
中古 ¥ 747
浅尾さんと倉田くん(3)(ガンガンコミックスONLINE)
(HERO)
新品 ¥ 690
中古 ¥ 370
7と嘘吐きオンライン―HERO個人作品集―(ガンガンコミックスONLIN...
(HERO)
新品 ¥ 710
中古 ¥ 158
ONE PIECE 65 (ジャンプコミックス)
(尾田 栄一郎)
NARUTO―ナルト― 59 (ジャンプコミックス)
(岸本 斉史)
ワンピース 海賊無双(通常版)(初回特典:オリジナルカスタムテーマ9種DLコード、ソーシャルゲーム専用レアフィギュア用コード同梱)
(バンダイナムコゲームス)
ドラゴンズドグマ(数量限定特典『バイオハザード6』体験版用DLコード同梱)
(カプコン)