Rails 在多态中使用状态机

Rails using state machine in polymorphic

我有这个多态模型。

class Note < ApplicationRecord

  belongs_to :notable, polymorphic: true, optional: false


  state_machine :is_status, initial: :pending do
    transition pending: :approved, on: %i[approve]
    transition pending: :cancelled, on: %i[cancel]
  end
end

和其他两个模型

class Invoice < ApplicationRecord

  has_many :notes, as: :notable, dependent: :destroy
end

class Person < ApplicationRecord

  has_many :notes, as: :notable, dependent: :destroy
end

如您所见,我附上了两种型号的便条,即个人或发票。并且还使用状态机。场景是我只想在 invoice 中使用状态机?这可能吗。 所以。如果我的 notable_type 是 "Invoice"。我得到我的状态是 "pending" 否则如果是我得到状态的人: nil

如我所见,可以通过notable_type == Invoice为条件给状态机过滤其他notable_types

可以参考AASMgem。 https://github.com/aasm/aasm .这不仅可以帮助您为所有转换添加保护方法,还可以帮助您在回调之前和之后添加保护方法。

您还可以添加一个 AASM 挂钩方法并在那里设置状态。例如:-

class Note < ApplicationRecord
  belongs_to :notable, polymorphic: true, optional: false
  include AASM
  aasm do
    state :pending
    state :approved
    state :cancelled
    event :approve do
      transitions from: :pending, to: :approved, before: some_method, after: some_method1
    end
    event :cancel do
      transitions from: :pending, to: :cancelled, before: some_method2, after: some_method3
    end
  end
    def aasm_ensure_initial_state
      if notable_type == "Invoice"
        self.aasm_state = :pending
      else
        self.aasm_state = nil
      end
    end
    def some_method
        puts "Some actions can be taken here."
    end
  end
end

我建议您创建一个封装状态机行为的新模型,然后将该模型附加到发票。

如果状态机旨在表示 Invoice 的状态,则将其设置为 InvoiceState belongs_to Invoice 和 Invoice has_one InvoiceState。

另一方面,如果您想使用此状态机来表示更一般的完整性概念,请将其命名为适当的通用名称(TransactionState 等)并通过多态关系附加它,例如 Note。

我描述的可能是这样的:

class Note < ApplicationRecord
  belongs_to :notable, polymorphic: true, optional: false
end

class Person < ApplicationRecord    
  has_many :notes, as: :notable, dependent: :destroy
end

class Invoice < ApplicationRecord    
  has_many :notes, as: :notable, dependent: :destroy
  has_one :invoice_state, dependent: :destroy
end

class InvoiceState < ApplicationRecord
  belongs_to :invoice, optional: false

  state_machine :status, initial: :pending do
    transition pending: :approved, on: %i[approve]
    transition pending: :cancelled, on: %i[cancel]
  end
end