目次
drive_by_state
AloneのAlControllerでは、通常は呼び出されるアクションはコントローラ名とアクション名により決定されますが、さらにステートという内部状態を利用して呼び出されるアクションを制御することができます。
アクションの実行をステートが特定の値の時のみに制限できるので、アクションが呼び出される順番を制限したり、想定外のアクションが呼び出されるのを防いだり、プログラムによってはより簡潔に処理ができたり等のメリットがあります。
ステートの設定とアクションの定義
コントローラ内でAlControllerBase#set_stateメソッドを呼ぶことにより、現在のステートを設定することができます。
set_state( "confirm" )
ステートが設定された状態では、コントローラ名、ステート名、アクション名の組み合わせにより実行されるメソッドが決定されます。例えば、ステータスが"confirm"でアアクション名が"commit"の場合、"from_confirm_action_commit"という名前のメソッドがアクションとして実行されます。
ステートの利用例
drive_by_stateサンプルはアクションを使ったプログラムの例です。ステートを利用することにより、確認画面を表示するアクションとフォームから送信された内容をセッション変数に設定するアクションの遷移元を特定のアクションに制限しています。利用者がwebブラウザのアドレスバーでアクションを直接指定しても、ステートが一致しなければそのアクションは実行されません。プログラマが想定していない順序で不正なアクションが実行されるのを防ぐことができます。
drive_by_stateサンプルの画面遷移
[入力画面] → [確認画面] ---------→ [完了画面] ↑ | (commit) -------------+ (cancel)
入力画面 (action_index)
アクション名がindexなので、アクション名が指定されていないときに実行されるデフォルトアクションです。入力画面が表示されます。メソッド名にステートを示すfrom_XXXXも指定されていないので、ステートの設定値にかかわらずアクセス可能です。
本アクション内で、ステート"init"を設定しています。
def action_index() session.delete_all() set_state( "init" ) AlTemplate.run( 'index.rhtml' ) end
確認画面 (from_init_action_confirm)
メソッド名に遷移元のアクションが"init"でなければならないことを示す"from_init_"がついています。本メソッド、ステートが"init"で指定されたアクションが"confirm"のときに実行されます。メソッド内ではステートを"confirm"に設定しています。
入力画面で set_state("init") が実行されていますので、この確認画面は入力画面からの遷移が可能です。
def from_init_action_confirm() if @form.validate() set_state( "confirm" ) session[:values] = @form.values AlTemplate.run( 'confirm.rhtml' ) else AlTemplate.run( 'index.rhtml' ) end end
完了画面 (from_confirm_action_commit)
メソッド名が"from_confirm_"から始まるので、このアクション"commit"はステートが"confirm"の時のみ実行可能です。確認画面でステートが"confirm"に設定されていますので、確認画面の次の遷移先としてこのアクションが呼び出し可能です。
メソッド内でステートを"finish"に設定しています。次の遷移先は最初の入力画面ですが、入力画面のためのアクション名は"action_index"であり遷移元のステートが指定されていないので、ステートの状態にかかわらず実行可能です。
def from_confirm_action_commit() set_state( "finish" ) @form.set_values( session[:values] ) AlTemplate.run( 'commit.rhtml' ) end
キャンセル画面 (from_confirm_action_cancel)
メソッド名が"from_confirm_"から始まるので、このアクション"cancel"はステートが"confirm"の時のみ実行可能です。すなわち、確認画面からの遷移が可能です。
def from_confirm_action_cancel() set_state( "init" ) @form.set_values( session[:values] ) AlTemplate.run( 'index.rhtml' ) session.delete( :values ) end