該軟件包包含AASM,一個用於在Ruby類中添加有限狀態機的庫。
AASM始於ACTS_AS_STATE_MACHINE插件,但已演變為更通用的庫,該庫不再僅針對ActivereCord模型。它目前為許多ORMS提供適配器,但無論其具有哪個父類別(如果有),都可以用於任何Ruby類。
查看readme_from_version_3_to_4有關如何從ASM的3.x版切換到4.0的詳細信息。
添加狀態機很簡單,就像包括AASM模塊並開始定義狀態和事件及其過渡:
class Job
include AASM
aasm do
state :sleeping , initial : true
state :running , :cleaning
event :run do
transitions from : :sleeping , to : :running
end
event :clean do
transitions from : :running , to : :cleaning
end
event :sleep do
transitions from : [ :running , :cleaning ] , to : :sleeping
end
end
end這為您提供了幾種課堂Job實例的公共方法:
job = Job . new
job . sleeping? # => true
job . may_run? # => true
job . run
job . running? # => true
job . sleeping? # => false
job . may_run? # => false
job . run # => raises AASM::InvalidTransition如果您不喜歡例外,並且喜歡簡單的true或false作為響應,請告訴Aasm不要發牢騷:
class Job
...
aasm whiny_transitions : false do
...
end
end
job . running? # => true
job . may_run? # => false
job . run # => false觸發事件時,您可以將塊傳遞到該方法,只有在過渡成功時才會調用它:
job . run do
job . user . notify_job_ran # Will be called if job.may_run? is true
end您可以為您的事件,過渡和狀態定義許多回調。當滿足某些標準時,將調用這些方法,PROCS或類,例如進入特定狀態:
class Job
include AASM
aasm do
state :sleeping , initial : true , before_enter : :do_something
state :running , before_enter : Proc . new { do_something && notify_somebody }
state :finished
after_all_transitions :log_status_change
event :run , after : :notify_somebody do
before do
log ( 'Preparing to run' )
end
transitions from : :sleeping , to : :running , after : Proc . new { |* args | set_process ( * args ) }
transitions from : :running , to : :finished , after : LogRunTime
end
event :sleep do
after do
...
end
error do | e |
...
end
transitions from : :running , to : :sleeping
end
end
def log_status_change
puts "changing from #{ aasm . from_state } to #{ aasm . to_state } (event: #{ aasm . current_event } )"
end
def set_process ( name )
...
end
def do_something
...
end
def notify_somebody
...
end
end
class LogRunTime
def call
log "Job was running for X seconds"
end
end在這種情況下,在實際進入狀態sleeping之前,請調用do_something ,而在過渡run (從sleeping到running )完成後,請調用notify_somebody 。
AASM還將在上面的示例中從running到finished後的過渡到完成後call LogRunTime 。您可以通過在上面定義初始化方法將參數傳遞給課程:這樣:
請注意,Procs是在記錄的上下文中執行的,這意味著您無需將記錄作為參數,只需調用所需的方法即可。
class LogRunTime
# optional args parameter can be omitted, but if you define initialize
# you must accept the model instance as the first parameter to it.
def initialize ( job , args = { } )
@job = job
end
def call
log "Job was running for #{ @job . run_time } seconds"
end
end 您可以將參數傳遞給事件:
job = Job . new
job . run ( :defragmentation )所有警衛和回調後都會收到這些參數。在這種情況下, set_process將與以下方式調用:defragmentation參數。
如果事件的第一個參數是狀態(例如:running或:finished ),則第一個參數被消耗,並且狀態機將嘗試過渡到該狀態。為後衛和回調添加逗號分隔參數
job = Job . new
job . run ( :running , :defragmentation )在這種情況下, set_process不會被調用,作業將過渡到運行狀態,而回調將接收:defragmentation為參數
如果在事件處理過程中發生錯誤的情況下,將救出錯誤並將其傳遞給:error回調,該錯誤可以處理或重新匯總以進行進一步傳播。
另外,您可以定義一個方法,如果任何事件失敗:
def aasm_event_failed ( event_name , old_state_name )
# use custom exception/messages, report metrics, etc
end在過渡期間:after (僅此而可靠地,或在全局after_all_transitions回調中),您可以訪問原始狀態(從國家 /地區)和目標狀態(to to nate),例如:
def set_process ( name )
logger . info "from #{ aasm . from_state } to #{ aasm . to_state } "
end 在這裡,您可以看到所有可能的回調列表,以及他們的呼叫順序:
begin
event before_all_events
event before
event guards
transition guards
old_state before_exit
old_state exit
after_all_transitions
transition after
new_state before_enter
new_state enter
... update state ...
event before_success # if persist successful
transition success # if persist successful, database update not guaranteed
event success # if persist successful, database update not guaranteed
old_state after_exit
new_state after_enter
event after
event after_all_events
rescue
event error
event error_on_all_events
ensure
event ensure
event ensure_on_all_events
end如果應該在數據庫更新後觸發事件的after_commit回調。
在運行回調時,您可以輕鬆地檢索通過使用aasm.current_event觸發的事件的名稱:
# taken the example callback from above
def do_something
puts "triggered #{ aasm . current_event } "
end進而
job = Job . new
# without bang
job . sleep # => triggered :sleep
# with bang
job . sleep! # => triggered :sleep!假設只有在給出定義的條件時,您才需要允許特定的過渡。為此,您可以在每個過渡之前設置一個警衛,該後期將在實際運行過渡之前運行。如果警衛隊返回false則過渡將被拒絕(提高AASM::InvalidTransition ):
class Cleaner
include AASM
aasm do
state :idle , initial : true
state :cleaning
event :clean do
transitions from : :idle , to : :cleaning , guard : :cleaning_needed?
end
event :clean_if_needed do
transitions from : :idle , to : :cleaning do
guard do
cleaning_needed?
end
end
transitions from : :idle , to : :idle
end
event :clean_if_dirty do
transitions from : :idle , to : :cleaning , guard : :if_dirty?
end
end
def cleaning_needed?
false
end
def if_dirty? ( status )
status == :dirty
end
end
job = Cleaner . new
job . may_clean? # => false
job . clean # => raises AASM::InvalidTransition
job . may_clean_if_needed? # => true
job . clean_if_needed! # idle
job . clean_if_dirty ( :clean ) # => raises AASM::InvalidTransition
job . clean_if_dirty ( :dirty ) # => true您甚至可以提供許多警衛,所有這些都必須成功繼續
def walked_the_dog? ; ... ; end
event :sleep do
transitions from : :running , to : :sleeping , guards : [ :cleaning_needed? , :walked_the_dog? ]
end如果您想為活動中的所有過渡提供警衛,可以使用事件警衛
event :sleep , guards : [ :walked_the_dog? ] do
transitions from : :running , to : :sleeping , guards : [ :cleaning_needed? ]
transitions from : :cleaning , to : :sleeping
end如果您喜歡更類似紅寶石的警衛語法,則可以使用if unless可以使用:
event :clean do
transitions from : :running , to : :cleaning , if : :cleaning_needed?
end
event :sleep do
transitions from : :running , to : :sleeping , unless : :cleaning_needed?
end
end如果班級響應call ,您可以調用課程而不是方法
event :sleep do
transitions from : :running , to : :sleeping , guards : Dog
end class Dog
def call
cleaning_needed? && walked?
end
...
end如果事件有多個過渡,成功完成的第一個過渡將阻止在同一事件中處理其他過渡。
require 'aasm'
class Job
include AASM
aasm do
state :stage1 , initial : true
state :stage2
state :stage3
state :completed
event :stage1_completed do
transitions from : :stage1 , to : :stage3 , guard : :stage2_completed?
transitions from : :stage1 , to : :stage2
end
end
def stage2_completed?
true
end
end
job = Job . new
job . stage1_completed
job . aasm . current_state # stage3您可以通過省略from方式來定義從任何定義狀態的過渡:
event :abort do
transitions to : :aborted
end您可以使用以下方式定義狀態顯示名稱
class Job
include AASM
aasm do
state :stage1 , initial : true , display : 'First Stage'
state :stage2
state :stage3
end
end
job = Job . new
job . aasm . human_state每個課程都支持多台狀態機。請注意,儘管考慮到每個班級的一台狀態機,但AASM已構建。儘管如此,這是這樣做的方法(見下文)。請注意,您將需要指定數據庫列為您的相關狀態存儲的位置 - 我們在下面的示例中指定了兩個列move_state和work_state 。有關更多信息,請參見“列”和“遷移”部分。
class SimpleMultipleExample
include AASM
aasm ( :move , column : 'move_state' ) do
state :standing , initial : true
state :walking
state :running
event :walk do
transitions from : :standing , to : :walking
end
event :run do
transitions from : [ :standing , :walking ] , to : :running
end
event :hold do
transitions from : [ :walking , :running ] , to : :standing
end
end
aasm ( :work , column : 'work_state' ) do
state :sleeping , initial : true
state :processing
event :start do
transitions from : :sleeping , to : :processing
end
event :stop do
transitions from : :processing , to : :sleeping
end
end
end
simple = SimpleMultipleExample . new
simple . aasm ( :move ) . current_state
# => :standing
simple . aasm ( :work ) . current_state
# => :sleeping
simple . start
simple . aasm ( :move ) . current_state
# => :standing
simple . aasm ( :work ) . current_state
# => :processing AASM不禁止在多個狀態機器中定義同一事件。如果沒有提供名稱空間,則最新的定義“獲勝”並覆蓋了先前的定義。但是,發出警告: SimpleMultipleExample: overriding method 'run'! 。
另外,您可以為每個狀態機提供一個名稱空間:
class NamespacedMultipleExample
include AASM
aasm ( :status ) do
state :unapproved , initial : true
state :approved
event :approve do
transitions from : :unapproved , to : :approved
end
event :unapprove do
transitions from : :approved , to : :unapproved
end
end
aasm ( :review_status , namespace : :review ) do
state :unapproved , initial : true
state :approved
event :approve do
transitions from : :unapproved , to : :approved
end
event :unapprove do
transitions from : :approved , to : :unapproved
end
end
end
namespaced = NamespacedMultipleExample . new
namespaced . aasm ( :status ) . current_state
# => :unapproved
namespaced . aasm ( :review_status ) . current_state
# => :unapproved
namespaced . approve_review
namespaced . aasm ( :review_status ) . current_state
# => :approved所有AASM類和實例級aasm方法都接受狀態計算機選擇器。因此,例如,要在班級上使用檢查,您必須使用
SimpleMultipleExample . aasm ( :move ) . states . map ( & :name )
# => [:standing, :walking, :running]允許事件綁定到另一個
class Example
include AASM
aasm ( :work ) do
state :sleeping , initial : true
state :processing
event :start do
transitions from : :sleeping , to : :processing
end
event :stop do
transitions from : :processing , to : :sleeping
end
end
aasm ( :question ) do
state :answered , initial : true
state :asked
event :ask , binding_event : :start do
transitions from : :answered , to : :asked
end
event :answer , binding_event : :stop do
transitions from : :asked , to : :answered
end
end
end
example = Example . new
example . aasm ( :work ) . current_state #=> :sleeping
example . aasm ( :question ) . current_state #=> :answered
example . ask
example . aasm ( :work ) . current_state #=> :processing
example . aasm ( :question ) . current_state #=> :askedAASM自動為每個狀態生成常數,因此您不必明確定義它們。
class Foo
include AASM
aasm do
state :initialized
state :calculated
state :finalized
end
end
> Foo :: STATE_INITIALIZED
#=> :initialized
> Foo :: STATE_CALCULATED
#=> :calculated AASM可讓您輕鬆地擴展AASM::Base出於自己的應用目的。
假設我們在許多AASM模型中都有共同的邏輯。我們可以在AASM::Base的子類中體現這種邏輯。
class CustomAASMBase < AASM :: Base
# A custom transition that we want available across many AASM models.
def count_transitions!
klass . class_eval do
aasm with_klass : CustomAASMBase do
after_all_transitions :increment_transition_count
end
end
end
# A custom annotation that we want available across many AASM models.
def requires_guards!
klass . class_eval do
attr_reader :authorizable_called ,
:transition_count ,
:fillable_called
def authorizable?
@authorizable_called = true
end
def fillable?
@fillable_called = true
end
def increment_transition_count
@transition_count ||= 0
@transition_count += 1
end
end
end
end當我們聲明具有AASM狀態計算機的模型時,我們只需將aasm塊帶有a :with_klass鍵的aasm塊。
class SimpleCustomExample
include AASM
# Let's build an AASM state machine with our custom class.
aasm with_klass : CustomAASMBase do
requires_guards!
count_transitions!
state :initialised , initial : true
state :filled_out
state :authorised
event :fill_out do
transitions from : :initialised , to : :filled_out , guard : :fillable?
end
event :authorise do
transitions from : :filled_out , to : :authorised , guard : :authorizable?
end
end
endAASM具有對ActivereCord的支持,並允許在數據庫中自動持續對象狀態。
將gem 'after_commit_everywhere', '~> 1.0'添加到您的gemfile。
class Job < ActiveRecord :: Base
include AASM
aasm do # default column: aasm_state
state :sleeping , initial : true
state :running
event :run do
transitions from : :sleeping , to : :running
end
event :sleep do
transitions from : :running , to : :sleeping
end
end
end您可以告訴AASM自動保存對像或將其保存下來
job = Job . new
job . run # not saved
job . run! # saved
# or
job . aasm . fire ( :run ) # not saved
job . aasm . fire! ( :run ) # saved保存包括在Job類上運行所有驗證。如果將whiny_persistence標誌設置為true ,則在失敗的情況下會增加異常。如果將whiny_persistence標誌設置為false ,則爆炸的方法返回true如果狀態過渡成功或false (如果發生錯誤)。
如果要確保在沒有運行驗證的情況下保存狀態(從而可以持續無效對象狀態),只需告訴AASM跳過驗證。請注意,在跳過驗證時,只有狀態列將在數據庫中進行更新(就像ActivereCord update_column正在工作一樣)。
class Job < ActiveRecord :: Base
include AASM
aasm skip_validation_on_save : true do
state :sleeping , initial : true
state :running
event :run do
transitions from : :sleeping , to : :running
end
event :sleep do
transitions from : :running , to : :sleeping
end
end
end另外,您可以使用some_event_name_without_validation!方法。因此,您可以靈活地默認情況下對所有過渡進行驗證,然後在需要時跳過它。請注意,只有如上示例中提到的狀態列會更新。
job . run_without_validation!如果要確保未直接分配用於存儲狀態的AASM列,請配置AASM以不允許直接分配,例如:
class Job < ActiveRecord :: Base
include AASM
aasm no_direct_assignment : true do
state :sleeping , initial : true
state :running
event :run do
transitions from : :sleeping , to : :running
end
end
end因此:
job = Job . create
job . aasm_state # => 'sleeping'
job . aasm_state = :running # => raises AASM::NoDirectAssignmentError
job . aasm_state # => 'sleeping'您可以告訴AASM在輸入新狀態時嘗試編寫時間戳。如果設置了timestamps: true , AASM將尋找一個名為“新狀態加_at的字段,並嘗試填充它:
class Job < ActiveRecord :: Base
include AASM
aasm timestamps : true do
state :sleeping , initial : true
state :running
event :run do
transitions from : :sleeping , to : :running
end
end
end因此:
job = Job . create
job . running_at # => nil
job . run!
job . running_at # => 2020-02-20 20:00:00缺少時間戳字段被默默地忽略,因此使用此選項時,沒有必要為所有狀態使用設置器(例如ActivereCord列)。
您可以在您的狀態列中使用Rails 4.1+中的枚舉:
class Job < ActiveRecord :: Base
include AASM
enum state : {
sleeping : 5 ,
running : 99
}
aasm column : :state , enum : true do
state :sleeping , initial : true
state :running
end
end您可以明確傳遞該方法的名稱,該方法可作為枚舉映射訪問作為enum的值,也可以簡單地將其設置為true 。在後一種情況下,AASM將嘗試使用多個列名稱訪問可能的枚舉狀態。
此外,如果您的列具有整數類型(通常是在使用Rails Enums工作時的情況),則可以省略:enum設置 - Aasm自動檢測到這種情況並啟用了枚舉支持。如果出現任何問題,您可以通過設置:enum到false禁用枚舉功能,並通過設置為默認行為。
除了Activerecord和Mongoid ,Aasm還支持續集。
class Job < Sequel :: Model
include AASM
aasm do # default column: aasm_state
...
end
end但是,它的功能尚未像activerecord那樣完整。例如,尚未定義範圍。請參閱自動示波器。
由於版本4.8.0 ASM還支持Dongrogoid作為持久性ORM。
如果您使用的是mongoid,AASM還支持對MongoDB的持久性。在包含aasm之前,請確保在包含aasm之前包含mongoid ::文檔。
class Job
include Mongoid :: Document
include AASM
field :aasm_state
aasm do
...
end
end如果您使用的是Nobrainer,AASM還支持持續重新InkinkDB。在包含aasm之前,請確保在包含aasm之前包含nobrainer ::文檔。
class Job
include NoBrainer :: Document
include AASM
field :aasm_state
aasm do
...
end
endAASM還通過redis ::對象支持Redis的持久性。在包含aasm之前,請確保包括redis ::對象。請注意,非爆炸事件將作為爆炸事件起作用,堅持每個呼叫的更改。
class User
include Redis :: Objects
include AASM
aasm do
end
endAASM將自動為模型中的每個狀態創建範圍方法。
class Job < ActiveRecord :: Base
include AASM
aasm do
state :sleeping , initial : true
state :running
state :cleaning
end
def self . sleeping
"This method name is already in use"
end
end class JobsController < ApplicationController
def index
@running_jobs = Job . running
@recent_cleaning_jobs = Job . cleaning . where ( 'created_at >= ?' , 3 . days . ago )
# @sleeping_jobs = Job.sleeping #=> "This method name is already in use"
end
end如果您不需要範圍(或根本不想要它們),請在定義AASM狀態時禁用它們的創建,例如:
class Job < ActiveRecord :: Base
include AASM
aasm create_scopes : false do
state :sleeping , initial : true
state :running
state :cleaning
end
end由於版本3.0.13 ASM支持ActivereCord交易。因此,每當過渡回調或狀態更新失敗時,所有數據庫記錄的所有更改都會回滾。 MongoDB不支持交易。
目前可以在活動中處理3個交易回調,以及所有活動的2個交易回調。
event before_all_transactions
event before_transaction
event aasm_fire_event ( within transaction )
event after_commit ( if event successful )
event after_transaction
event after_all_transactions如果要確保僅在進行交易後才發生依賴訴訟,請使用after_commit回調以及自動保存(BANG)方法,例如:
class Job < ActiveRecord :: Base
include AASM
aasm do
state :sleeping , initial : true
state :running
event :run , after_commit : :notify_about_running_job do
transitions from : :sleeping , to : :running
end
end
def notify_about_running_job
...
end
end
job = Job . where ( state : 'sleeping' ) . first!
job . run! # Saves the model and triggers the after_commit callback請注意,以下內容不會運行after_commit回調,因為未使用自動保存方法:
job = Job . where ( state : 'sleeping' ) . first!
job . run
job . save! #notify_about_running_job is not run請注意:after_commit aasm回調圍繞交易模式的自定義實現而不是真實的數據庫事務。這一事實仍然導致種族條件和嵌套交易中的冗餘回調調用。為了解決該問題,強烈建議將gem 'after_commit_everywhere', '~> 1.0'添加到您的Gemfile中,〜> 1.0'。
如果要將狀態變化封裝在自己的交易中,則此嵌套交易的行為可能會造成混淆。如果您想進一步了解此事,請看一下ActivereCord嵌套交易。然而,默認情況下,AASM需要一項新的事務transaction(requires_new: true) 。您可以通過更改配置來覆蓋此行為
class Job < ActiveRecord :: Base
include AASM
aasm requires_new_transaction : false do
...
end
...
end然後導致transaction(requires_new: false) ,導軌默認值。
此外,如果您不希望將任何ActiverEcord操作包裹在交易中,則可以指定use_transactions標誌。如果您想將事物持續到由於事務或回調而發生的數據庫,即使發生某些錯誤,這可能會很有用。默認情況下, use_transactions標誌是正確的。
class Job < ActiveRecord :: Base
include AASM
aasm use_transactions : false do
...
end
...
endAASM支持Activerecord的悲觀鎖定, with_lock用於數據庫持久性層。
| 選項 | 目的 |
|---|---|
false (默認) | 沒有鎖 |
true | 獲得阻止悲觀鎖,例如FOR UPDATE |
| 細繩 | 根據SQL字符串獲得鎖,例如FOR UPDATE NOWAIT |
class Job < ActiveRecord :: Base
include AASM
aasm requires_lock : true do
...
end
...
end class Job < ActiveRecord :: Base
include AASM
aasm requires_lock : 'FOR UPDATE NOWAIT' do
...
end
...
end作為默認,AASM使用列aasm_state存儲狀態。您可以通過定義您喜歡的列名,使用以下列來覆蓋此:column :
class Job < ActiveRecord :: Base
include AASM
aasm column : :my_state do
...
end
aasm :another_state_machine , column : :second_state do
...
end
end無論使用哪種列名稱,請確保添加遷移以提供此列(類型string )。請勿在數據庫級別添加列的默認值。如果您在數據庫中添加默認值,則在模型實例化後將不會觸發初始狀態的AASM回調。
class AddJobState < ActiveRecord :: Migration
def self . up
add_column :jobs , :aasm_state , :string
end
def self . down
remove_column :jobs , :aasm_state
end
end可以使用Paper_trail Gem進行記錄狀態更改
可以在此處找到實施的示例
AASM支持有關狀態和事件的查詢方法
給定以下Job類:
class Job
include AASM
aasm do
state :sleeping , initial : true
state :running , :cleaning
event :run do
transitions from : :sleeping , to : :running
end
event :clean do
transitions from : :running , to : :cleaning , guard : :cleaning_needed?
end
event :sleep do
transitions from : [ :running , :cleaning ] , to : :sleeping
end
end
def cleaning_needed?
false
end
end # show all states
Job . aasm . states . map ( & :name )
#=> [:sleeping, :running, :cleaning]
job = Job . new
# show all permitted states (from initial state)
job . aasm . states ( permitted : true ) . map ( & :name )
#=> [:running]
# List all the permitted transitions(event and state pairs) from initial state
job . aasm . permitted_transitions
#=> [{ :event => :run, :state => :running }]
job . run
job . aasm . states ( permitted : true ) . map ( & :name )
#=> [:sleeping]
# show all non permitted states
job . aasm . states ( permitted : false ) . map ( & :name )
#=> [:cleaning]
# show all possible (triggerable) events from the current state
job . aasm . events . map ( & :name )
#=> [:clean, :sleep]
# show all permitted events
job . aasm . events ( permitted : true ) . map ( & :name )
#=> [:sleep]
# show all non permitted events
job . aasm . events ( permitted : false ) . map ( & :name )
#=> [:clean]
# show all possible events except a specific one
job . aasm . events ( reject : :sleep ) . map ( & :name )
#=> [:clean]
# list states for select
Job . aasm . states_for_select
#=> [["Sleeping", "sleeping"], ["Running", "running"], ["Cleaning", "cleaning"]]
# show permitted states with guard parameter
job . aasm . states ( { permitted : true } , guard_parameter ) . map ( & :name )默認情況下,警告將打印到STDERR 。如果要將這些警告記錄到另一個輸出,請使用
class Job
include AASM
aasm logger : Rails . logger do
...
end
end您可以通過設置AASM::Configuration.hide_warnings = true隱藏警告
現在支持Codedataquery!但是,我仍在向其存儲庫提交兼容性更新。同時,您可以使用我的叉子,可能仍然存在一些小問題,但我打算自己廣泛使用它,因此修復程序應該很快。
警告:
AASM為RSPEC提供了一些匹配器:
transition_from ,have_state , allow_eventallow_transition_to 。 require 'aasm/rspec'到您的spec_helper.rb文件。 # classes with only the default state machine
job = Job . new
expect ( job ) . to transition_from ( :sleeping ) . to ( :running ) . on_event ( :run )
expect ( job ) . not_to transition_from ( :sleeping ) . to ( :cleaning ) . on_event ( :run )
expect ( job ) . to have_state ( :sleeping )
expect ( job ) . not_to have_state ( :running )
expect ( job ) . to allow_event :run
expect ( job ) . to_not allow_event :clean
expect ( job ) . to allow_transition_to ( :running )
expect ( job ) . to_not allow_transition_to ( :cleaning )
# on_event also accept multiple arguments
expect ( job ) . to transition_from ( :sleeping ) . to ( :running ) . on_event ( :run , :defragmentation )
# classes with multiple state machine
multiple = SimpleMultipleExample . new
expect ( multiple ) . to transition_from ( :standing ) . to ( :walking ) . on_event ( :walk ) . on ( :move )
expect ( multiple ) . to_not transition_from ( :standing ) . to ( :running ) . on_event ( :walk ) . on ( :move )
expect ( multiple ) . to have_state ( :standing ) . on ( :move )
expect ( multiple ) . not_to have_state ( :walking ) . on ( :move )
expect ( multiple ) . to allow_event ( :walk ) . on ( :move )
expect ( multiple ) . to_not allow_event ( :hold ) . on ( :move )
expect ( multiple ) . to allow_transition_to ( :walking ) . on ( :move )
expect ( multiple ) . to_not allow_transition_to ( :running ) . on ( :move )
expect ( multiple ) . to transition_from ( :sleeping ) . to ( :processing ) . on_event ( :start ) . on ( :work )
expect ( multiple ) . to_not transition_from ( :sleeping ) . to ( :sleeping ) . on_event ( :start ) . on ( :work )
expect ( multiple ) . to have_state ( :sleeping ) . on ( :work )
expect ( multiple ) . not_to have_state ( :processing ) . on ( :work )
expect ( multiple ) . to allow_event ( :start ) . on ( :move )
expect ( multiple ) . to_not allow_event ( :stop ) . on ( :move )
expect ( multiple ) . to allow_transition_to ( :processing ) . on ( :move )
expect ( multiple ) . to_not allow_transition_to ( :sleeping ) . on ( :move )
# allow_event also accepts arguments
expect ( job ) . to allow_event ( :run ) . with ( :defragmentation ) AASM提供了對最大的斷言和類似RSPEC的期望。
支持斷言的列表: assert_have_state , refute_have_state , assert_transitions_from , refute_transitions_from , assert_event_allowed , refute_event_allowed ,assert_transition_lowled, assert_transition_to_allowed , refute_transition_to_allowed 。
在您的test_helper.rb文件中添加require 'aasm/minitest' ,然後以這樣的方式使用它們:
# classes with only the default state machine
job = Job . new
assert_transitions_from job , :sleeping , to : :running , on_event : :run
refute_transitions_from job , :sleeping , to : :cleaning , on_event : :run
assert_have_state job , :sleeping
refute_have_state job , :running
assert_event_allowed job , :run
refute_event_allowed job , :clean
assert_transition_to_allowed job , :running
refute_transition_to_allowed job , :cleaning
# on_event also accept arguments
assert_transitions_from job , :sleeping , :defragmentation , to : :running , on_event : :run
# classes with multiple state machine
multiple = SimpleMultipleExample . new
assert_transitions_from multiple , :standing , to : :walking , on_event : :walk , on : :move
refute_transitions_from multiple , :standing , to : :running , on_event : :walk , on : :move
assert_have_state multiple , :standing , on : :move
refute_have_state multiple , :walking , on : :move
assert_event_allowed multiple , :walk , on : :move
refute_event_allowed multiple , :hold , on : :move
assert_transition_to_allowed multiple , :walking , on : :move
refute_transition_to_allowed multiple , :running , on : :move
assert_transitions_from multiple , :sleeping , to : :processing , on_event : :start , on : :work
refute_transitions_from multiple , :sleeping , to : :sleeping , on_event : :start , on : :work
assert_have_state multiple , :sleeping , on : :work
refute_have_state multiple , :processing , on : :work
assert_event_allowed multiple , :start , on : :move
refute_event_allowed multiple , :stop , on : :move
assert_transition_to_allowed multiple , :processing , on : :move
refute_transition_to_allowed multiple , :sleeping , on : :move 支持的期望列表: must_transition_from , wont_transition_from , must_have_state , wont_have_state , must_allow_event , wont_allow_event , wont_allow_transition_to must_allow_transition_to
在您的test_helper.rb文件中添加require 'aasm/minitest_spec' ,然後以這樣的方式使用它們:
# classes with only the default state machine
job = Job . new
job . must_transition_from :sleeping , to : :running , on_event : :run
job . wont_transition_from :sleeping , to : :cleaning , on_event : :run
job . must_have_state :sleeping
job . wont_have_state :running
job . must_allow_event :run
job . wont_allow_event :clean
job . must_allow_transition_to :running
job . wont_allow_transition_to :cleaning
# on_event also accept arguments
job . must_transition_from :sleeping , :defragmentation , to : :running , on_event : :run
# classes with multiple state machine
multiple = SimpleMultipleExample . new
multiple . must_transition_from :standing , to : :walking , on_event : :walk , on : :move
multiple . wont_transition_from :standing , to : :running , on_event : :walk , on : :move
multiple . must_have_state :standing , on : :move
multiple . wont_have_state :walking , on : :move
multiple . must_allow_event :walk , on : :move
multiple . wont_allow_event :hold , on : :move
multiple . must_allow_transition_to :walking , on : :move
multiple . wont_allow_transition_to :running , on : :move
multiple . must_transition_from :sleeping , to : :processing , on_event : :start , on : :work
multiple . wont_transition_from :sleeping , to : :sleeping , on_event : :start , on : :work
multiple . must_have_state :sleeping , on : :work
multiple . wont_have_state :processing , on : :work
multiple . must_allow_event :start , on : :move
multiple . wont_allow_event :stop , on : :move
multiple . must_allow_transition_to :processing , on : :move
multiple . wont_allow_transition_to :sleeping , on : :move % gem install aasm # Gemfile
gem 'aasm'% rake build
% sudo gem install pkg/aasm-x.y.z.gem安裝AASM後,您可以運行生成器:
% rails generate aasm NAME [COLUMN_NAME]用模型名稱替換名稱,column_name是可選的(默認為'aasm_state')。這將創建一個模型(如果不存在的話)並使用AASM塊進行配置。對於ActiverEcord Orm,添加了遷移文件以將AASM狀態列添加到表。
輕鬆在Docker上運行測試套件
1. docker-compose build aasm
2. docker-compose run --rm aasm
查看ChangElog,以獲取有關當前版本最近更改的詳細信息。
隨意
aasm的標籤)該軟件是“原樣”提供的,並且沒有任何明示或暗示的保證,包括但不限於對特定目的的商人和適合性的隱含保證。
版權(C)2006-2017 Scott Barron
特此免費授予獲得此軟件副本和相關文檔文件副本(“軟件”)的任何人,以無限制處理該軟件,包括無限制的使用權,複製,複製,修改,合併,合併,發布,分發,分發,分發,訂婚,和/或允許軟件的副本,並允許對以下條件提供以下條件,以下是以下條件。
上述版權通知和此許可通知應包含在軟件的所有副本或大量部分中。
該軟件是“原樣”提供的,沒有任何形式的明示或暗示保證,包括但不限於適銷性,特定目的的適用性和非侵權的保證。在任何情況下,作者或版權持有人都不應對任何索賠,損害賠償或其他責任責任,無論是在合同,侵權的訴訟中還是其他責任,是由軟件,使用或與軟件中的使用或其他交易有關的。