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
我有这个多态模型。
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