こんにちは。ハートレイルズの前島(@netwillnet)です。今回は aasm という、状態遷移をスマートに管理するためのRailsプラグインの紹介をしようと思います。
gem install aasm
だけ。
複数の状態を持つモデルを管理するときに威力を発揮します。例として、所有している本の状態を管理するモデルを書いてみましょう。状態には
の4つがあるとし、 status カラムで管理します。また、別の状態として「友達に貸している」を管理する lending カラムを定義しているとします。
状態遷移系のメソッドを aasm を使わず、素直に書くと
class Book < ActiveRecord::Base
# status : 読書の状態を管理するカラム(integer)
# lending : 友達に貸しているか否かを管理するカラム(boolean)
before_create :set_initial_state
STATUS = {:not_read => 0, :reading => 1, :read => 2, :dump => 3}
def reading
# 未読以外の状態/友達に貸している状態からは遷移させない
if !status.nil? && status != STATUS[:not_read] || lending
return
end
self.status = STATUS[:reading]
end
def read
# 未読/読んでる途中以外の状態/友達に貸している状態からは遷移させない
return if !status.nil? && status != STATUS[:not_read] && status != STATUS[:reading] || lending
self.status = STATUS[:read]
end
def dump
# 友達に貸している状態からは遷移させない
return if lending
self.status = STATUS[:dump]
end
private
def set_initial_state
self.status = STATUS[:not_read] if status.nil?
end
end
こんな感じでしょうか。これくらいなら別に aasm を導入しなくても何とかなりますが、状態遷移させるかどうか判定する条件式が面倒ですね。もし、状態の数や条件がもっと多かったらどうでしょう・・・うんざりしてきますね。
これを aasm を使って書くと下記のようになります。
class Book < ActiveRecord::Base
# status : 読書の状態を管理するカラム(string)
# lending : 友達に貸しているか否かを管理するカラム(boolean)
include AASM
aasm_column :status
aasm_initial_state :not_read
aasm_state :not_read
aasm_state :reading
aasm_state :read
aasm_state :dump
aasm_event :reading do
transitions :to => :read, :from => :not_read, :guard => :not_lending?
end
aasm_event :read do
transitions :to => :read, :from => [:not_read, :reading], :guard => :not_lending?
end
aasm_event :dump do
transitions :to => :dump, :from => [:not_read, :reading, :read], :guard => :not_lending?
end
def not_lending?
!lending
end
end
どうでしょうか。だいぶすっきりしたように思いませんか?
コードを見れば大体わかると思いますが、簡単に説明します。
というわけで、 aasm を使うとこのような感じで複雑な状態管理をスマートに書くことが出来ます。みなさんも使ってみてはどうでしょうか。
ハートレイルズは新規事業開発のエキスパートです。詳しくは コーポレートサイト をご覧ください。