其目的是仅允许为属性定义值,并仅允许从一种状态到另一种状态的预定义转换。例如,状态 A 可以在状态 B 或状态 C 中转移,但状态 B 不能在状态 C 中转移。此外,AASM 提供了一些回调方法来控制转换或在转换之前或之后执行某些操作。
我在用户模型中使用 AASM 以确保用户状态只能以预定义的方式更改。看例子:
# THE STATE MACHINE ----------------------------------------------------------
INITIAL_STATE = :pending
STATES = {
INITIAL_STATE => 'new user accounts initial state',
:waiting => 'new user account is waiting for confirmation',
:confirmed => 'user confirmed the registration',
:changing_email => 'user changed its email address',
:blocked => 'user can not log in',
:anonymized => 'personal user data deleted',
:not_deletable => 'can not delete user, because he has some content'
}
include AASM
attr_protected :state
aasm({:column => :state}) do
STATES.keys.each do |key|
state(key, (key == INITIAL_STATE ? {:initial => true} : {}))
end
# creates instance methods confirm, confirm! and confirmed? for later usage
event :confirm do
transitions :to => :confirmed, :from => :waiting
transitions :to => :confirmed, :from => :blocked
transitions :to => :confirmed, :from => :changing_email
transitions :to => :confirmed, :from => :not_deletable
end
end
在事件块中,我定义了如何确认用户状态。因此 user.state 属性必须是“waiting”、“blocked”、“changeing_email”或“not_deleteable”。在这些情况下,您可以调用 AASM 引入的一些魔术方法。
user.confirmed?
# => false
现在您可以确认用户了。
user.confirm
user.state
# => confirmed
或者
user.confirm!
# => true
user.state
# => confirmed
现在
user.confirmed?
# => true
如果我的用户处于“匿名”状态,那么我无法确认它并会收到错误消息。这样我的用户实例在任何时候都有明确定义的状态。更改用户状态时我不会出错。我只使用 AASM 中定义的方法来执行此操作。只能执行已定义的状态和已定义的转换。