AASM 的基本状态

通常,你最终会创建包含状态的模型,并且该状态将在对象的生命周期内发生变化。

AASM 是一个有限状态机启用程序库,可以帮助你轻松完成对象的流程设计。

在你的模型中有这样的东西与 Fat Model,Skinny Controller 的想法完全一致,这是 Rails 最佳实践之一。该模型唯一负责管理其状态,其变化以及生成由这些变化触发的事件。

要在 Gemfile 中安装

gem 'aasm'

考虑一个应用程序,其中用户引用产品的价格。

class Quote

  include AASM

  aasm do
    state :requested, initial: true  # User sees a product and requests a quote
    state :priced                    # Seller sets the price 
    state :payed                     # Buyer pays the price
    state :canceled                  # The buyer is not willing to pay the price
    state :completed                 # The product has been delivered.

    event :price do
        transitions from: requested, to: :priced
    end

    event :pay do
        transitions from: :priced, to: :payed, success: :set_payment_date
    end

    event :complete do
        transitions from: :payed, to: :completed, guard: product_delivered?
    end

    event :cancel do
        transitions from: [:requested, :priced], to: :canceled
        transitions from: :payed, to: canceled, success: :reverse_charges
    end

   
  end

  private

  def set_payment_date
    update payed_at: Time.zone.now
  end
end

Quote 类的状态可以去,但它最适合你的过程。

你可以将状态视为过去,如前面的示例或其他时态的算法,例如:定价,支付,交付等。状态的命名取决于你。从个人角度来看,过去的状态更好地工作,因为你的最终状态肯定会是过去的行为并且更好地与事件名称联系起来,这将在后面解释。

注意: 注意你使用的名称,你必须担心不使用 Ruby 或 Ruby on Rails 保留的关键字,如 validendbeing 等。

定义了状态和转换后,我们现在可以访问 AASM 创建的一些方法。

例如:

Quote.priced  # Shows all Quotes with priced events
quote.priced? # Indicates if that specific quote has been priced
quote.price!  # Triggers the event the would transition from requested to priced.

正如你所看到的,事件具有转换,此转换决定了状态在事件调用时的更改方式。如果事件由于当前状态而无效,则将引发错误。

例如,事件和转换还有一些其他回调

guard: product_delivered?

将调用将返回布尔值的 product_delivered? 方法。如果结果为 false,则不会应用转换,如果没有其他转换可用,则状态不会更改。

success: :reverse_charges

如果该翻译成功发生,则将调用:reverse_charges 方法。

AASM 中还有其他几种方法,在此过程中有更多回调,但这将帮助你创建具有有限状态的第一个模型。