Skip to content
state_flow plugin provides a DSL to define flow of state with ActiveRecord
Ruby
Find file
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
lib
spec
tasks
.gitignore
MIT-LICENSE
README.rdoc
Rakefile
VERSION
init.rb
install.rb
uninstall.rb

README.rdoc

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

Something went wrong with that request. Please try again.