StateFlow
StateFlowとは?
状態遷移のためのDSLを提供するためのActiveRecordを拡張するプラグインです。
基本的にUMLのステートチャート図に忠実に状態遷移を記述できるようにすることが最終目標です。 現在のところ、以下のような機能があります。
* イベント/ガード/アクションの設定
* イベントとして定義可能なのは、以下の通りです。
* モデルに対する任意の名前のアクション(メソッドとして定義されるので、メソッド名に被っていると上書きされます)。
* アクションの戻り値
* 例外
* ガードはその条件に該当するかどうかを判断するメソッド名を指定します。
* アクションはモデルのメソッドを指定しますが、状態を変更するコードは不要です。
* 状態の遷移は自動で行われます。
* 状態のネスト
* 親の状態で定義されたイベントが実行された場合に正しく状態を遷移します。
* 状態を遷移する際のトランザクションの制御
* 各状態間の遷移毎にトランザクションを発行します。
* 例外発生時などにはロールバックを行い、(指定されていれば)例外に対応する状態に遷移してモデルを保存します。
サンプル
以下のような記述が可能です。
class Order < ActiveRecord::Base
class StockShortageError < StandardError
end
selectable_attr :status_cd do
entry '00', :waiting_settling , '決済前'
entry '01', :online_settling , '決済中'
entry '02', :receiving , '入金待ち'
entry '03', :deliver_preparing, '配送準備中'
end
state_flow(:status_cd) do
origin(:waiting_settling)
group(:valid) do
from(:waiting_settling) do
guard(:pay_cash_on_delivery?).action(:reserve_point).action(:reserve_stock){
event(:reserve_stock_ok).to(:deliver_preparing)
event_else.action(:delete_point).to(:stock_error)
}
guard_else.action(:reserve_point).action(:reserve_stock, :temporary => true){
event(:reserve_stock_ok){
guard(:bank_deposit?).action(:send_mail_thanks).to(:receiving)
guard(:credit_card?).to(:online_settling)
guard(:foreign_payment?).action(:settle).to(:online_settling)
}
event_else{
guard(:foreign_payment?).action(:delete_point).action(:send_mail_stock_shortage)
}.to(:stock_error)
}
recover(StockShortageError).to(:stock_error)
end
from(:online_settling) do
guard(:credit_card?).action(:settle){
event(:ok).action(:reserve_stock).action(:send_mail_thanks).to(:deliver_preparing)
event_else.action(:release_stock).action(:delete_point).to(:settlement_error)
}
guard(:foreign_payment?){
event(:settlement_ok).to(:deliver_preparing)
event(:settlement_ng).action(:release_stock).action(:delete_point).action(:send_mail_invalid_purchage).to(:settlement_error)
}
recover(Exception).action(:release_stock).action(:delete_point).to(:settlement_error)
end
end
end
end
詳しくはspec/order_spec.rbをご覧ください。
セットアップ
state_flowプラグインはselectable_attrに依存しています。
-
selectable_attr
– github.com/akm/selectable_attr
-
selectable_attr_rails
– github.com/akm/selectable_attr_rails
Railsで使う場合
プラグインとしてインストール
ruby script/plugin install git://github.com/akm/selectable_attr.git
ruby script/plugin install git://github.com/akm/selectable_attr_rails.git
ruby script/plugin install git://github.com/akm/state_flow.git
でオッケーです。
gemの場合
まずgemcutterの設定をしていなかったら、
gem install gemcutter
gem tumble
を実行した後、
gem install selectable_attr selectable_attr_rails state_flow
を実行するとインストール完了。
で、config/initializersに以下の2つのファイルを作成すればオッケーです。
config/initializers/selectable_attr.rb
require 'selectable_attr'
require 'selectable_attr_i18n'
require 'selectable_attr_rails'
SelectableAttrRails.add_features_to_rails
config/initializers/state_flow.rb
require 'state_flow'
ActiveRecord::Base.module_eval do
include StateFlow
end
Example
以下のテスト用のモデルや、テストをご覧ください。 github.com/akm/state_flow/blob/master/spec/resources/models/order.rb github.com/akm/state_flow/blob/master/spec/order_spec.rb
Copyright © 2009 [Takeshi AKIMA], released under the MIT license