該特定狀態機的想法是將驗證聲明嵌入到狀態中。
state :orange do
validate :validate_core
end
無論何時對象正在轉換爲橙色,上述配置將執行驗證:validate_core
。
event :orangify do
transition all => :orange
end
我明白您對回滾的關注,但請記住,回滾是在交易中執行的,因此它非常便宜。
record.orangify!
此外,請記住,您還可以使用不使用異常的非爆炸版本。
> c.orangify
(0.3ms) BEGIN
(0.3ms) ROLLBACK
=> false
這就是說,如果你想使用基於之前的過渡採用不同的方法,那麼你只需要知道,如果回調返回false,過渡被暫停。
before_transition do
false
end
> c.orangify!
(0.2ms) BEGIN
(0.2ms) ROLLBACK
StateMachine::InvalidTransition: Cannot transition state via :cancel from :purchased (Reason(s): Transition halted)
注意交易開始工作,但它有可能,如果回調是在開始的時候不會執行查詢。
before_transaction
接受一些參數。您可以產生對象和事務實例。
before_transition do |object, transaction|
object.validate_core
end
,確實可以通過事件
before_transition all => :orange do |object, transaction|
object.validate_core # => false
end
在這種情況下,限制它,但是validate_core
應該是返回真/假的簡單方法。如果你想使用定義的驗證鏈,那麼我想到的是在模型本身上調用valid?
。
before_transition all => :orange do |object, transaction|
object.valid?
end
但是,請注意,您不能在事務範圍之外運行事務。事實上,如果您檢查perform
的代碼,您將看到回調在交易中。
# Runs each of the collection's transitions in parallel.
#
# All transitions will run through the following steps:
# 1. Before callbacks
# 2. Persist state
# 3. Invoke action
# 4. After callbacks (if configured)
# 5. Rollback (if action is unsuccessful)
#
# If a block is passed to this method, that block will be called instead
# of invoking each transition's action.
def perform(&block)
reset
if valid?
if use_event_attributes? && !block_given?
each do |transition|
transition.transient = true
transition.machine.write(object, :event_transition, transition)
end
run_actions
else
within_transaction do
catch(:halt) { run_callbacks(&block) }
rollback unless success?
end
end
end
# ...
end
要跳過的事務,您應該猴補丁state_machine使過渡方法(如)檢查記錄是否轉換之前有效。
下面是你應該實現
# Override orangify! state machine action
# If the record is valid, then perform the actual transition,
# otherwise return early.
def orangify!(*args)
return false unless self.valid?
super
end
當然什麼一個例子,你不能這樣做手工爲每個方法,這就是爲什麼你應該猴子補丁庫實現這一結果。
問題不在於回滾的性能,更多的是保存通過(至少在最初)。因此,在我的控制器中,嚮導爲控制器供電,控制器檢查保存並繼續運行,並使用戶進入下一步。與此同時,背景中的狀態回滾和用戶現在正處於他們不應訪問的步驟。我在我的控制器中有一個明確的檢查,但感覺像不需要的混亂。 –
您是否試圖按照我所示的方式返回false?它應該停止轉換。 –
我做過了,它確實如此,但它仍然作爲回滾。我將更新我的問題以更好地反映我正在尋找的內容。我做了一個假設,即在before_transition上停止狀態轉換將會停止回滾,但事實並非如此。 –