こんにちは。ハートレイルズの前島(@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? endendこんな感じでしょうか。これくらいなら別に 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 endendどうでしょうか。だいぶすっきりしたように思いませんか?
コードを見れば大体わかると思いますが、簡単に説明します。
というわけで、 aasm を使うとこのような感じで複雑な状態管理をスマートに書くことが出来ます。みなさんも使ってみてはどうでしょうか。
ハートレイルズは新規事業開発のエキスパートです。詳しくはコーポレートサイトをご覧ください。