Archive for January 2010
- In: Ruby | Ruby on Rails
- 5 Comments
This morning I ran into a small roadblock working with the acts_as_state_machine gem. My code started like this:
class Communication < ActiveRecord::Base
include AASM
aasm_column :status
aasm_state :draft
aasm_state :pending
aasm_state :approved
aasm_state :rejected
aasm_event :submit do
transitions :to => :pending, :from => :draft
end
aasm_event :approve do
transitions :to => :approved, :from => [:pending, :rejected]
end
aasm_event :reject do
transitions :to => :rejected, :from => [:pending, :approved], :guard => :validate_rejection_reason
end
aasm_initial_state :draft
def validate_rejection_reason
if self.rejection_reason
true
else
raise AASM::InvalidTransition.new('A rejection reason is required')
end
end
end
This is a basic example using AASM to provide an approval process for my Communication model. I wanted the ability to just call instance.reject(“some reason”) or instance.reject!(“some reason”). I was really thinking to hard about it. The assm_event just creates some methods for me….so why not just decorate those methods using ruby aliases. This is what I ended up with:
include AASM
aasm_column :status
aasm_state :draft
aasm_state :pending
aasm_state :approved
aasm_state :rejected
aasm_event :submit do
transitions :to => :pending, :from => :draft
end
aasm_event :approve do
transitions :to => :approved, :from => [:pending, :rejected]
end
aasm_event :reject do
transitions :to => :rejected, :from => [:pending, :approved], :guard => :validate_rejection_reason
end
alias old_reject reject
alias old_reject! reject!
aasm_initial_state :draft
def reject(reason)
self.rejection_reason = reason
self.old_reject
end
def reject!(reason)
self.rejection_reason = reason
self.old_reject!
end
def validate_rejection_reason
if self.rejection_reason
true
else
raise AASM::InvalidTransition.new('A rejection reason is required')
end
end
Notice the use of alias for reject and reject!. Now you have to call reject with a rejection reason. There may be another way to get parameters in to the event call….but this is how I rolled mine