Allow namespacing methods and state constants

This commit is contained in:
Cory Kaufman-Schofield 2015-09-22 16:22:05 -04:00
parent 5b885c8a0d
commit 86126c7c90
4 changed files with 115 additions and 5 deletions

View File

@ -29,6 +29,9 @@ module AASM
configure :enum, nil
# Set to true to namespace reader methods and constants
configure :namespace, false
# make sure to raise an error if no_direct_assignment is enabled
# and attribute is directly assigned though
@klass.class_eval %Q(
@ -66,18 +69,30 @@ module AASM
def state(name, options={})
@state_machine.add_state(name, @klass, options)
if @klass.instance_methods.include?("#{name}?")
if namespace?
method_name = "#{namespace}_#{name}"
else
method_name = name
end
if @klass.instance_methods.include?("#{method_name}?")
warn "#{@klass.name}: The state name #{name} is already used!"
end
@klass.class_eval <<-EORUBY, __FILE__, __LINE__ + 1
def #{name}?
def #{method_name}?
aasm(:#{@name}).current_state == :#{name}
end
EORUBY
unless @klass.const_defined?("STATE_#{name.upcase}")
@klass.const_set("STATE_#{name.upcase}", name)
if namespace?
const_name = "STATE_#{namespace.upcase}_#{name.upcase}"
else
const_name = "STATE_#{name.upcase}"
end
unless @klass.const_defined?(const_name)
@klass.const_set(const_name, name)
end
end
@ -148,5 +163,16 @@ module AASM
end
end
def namespace?
!!@state_machine.config.namespace
end
def namespace
if @state_machine.config.namespace == true
@name
else
@state_machine.config.namespace
end
end
end
end

View File

@ -19,5 +19,8 @@ module AASM
attr_accessor :no_direct_assignment
attr_accessor :enum
# namespace reader methods and constants
attr_accessor :namespace
end
end
end

View File

@ -0,0 +1,28 @@
class NamespacedMultipleExample
include AASM
aasm(:status) do
state :unapproved, :initial => true
state :approved
event :approve do
transitions :from => :unapproved, :to => :approved
end
event :unapprove do
transitions :from => :approved, :to => :unapproved
end
end
aasm(:review_status, namespace: :review) do
state :unapproved, :initial => true
state :approved
event :approve_review do
transitions :from => :unapproved, :to => :approved
end
event :unapprove_review do
transitions :from => :approved, :to => :unapproved
end
end
end

View File

@ -0,0 +1,53 @@
require 'spec_helper'
describe 'state machine' do
let(:namespaced) { NamespacedMultipleExample.new }
it 'starts with an initial state' do
expect(namespaced.aasm(:status).current_state).to eq(:unapproved)
expect(namespaced).to respond_to(:unapproved?)
expect(namespaced).to be_unapproved
expect(namespaced.aasm(:review_status).current_state).to eq(:unapproved)
expect(namespaced).to respond_to(:review_unapproved?)
expect(namespaced).to be_review_unapproved
end
it 'allows transitions to other states' do
expect(namespaced).to respond_to(:approve)
expect(namespaced).to respond_to(:approve!)
namespaced.approve!
expect(namespaced).to respond_to(:approved?)
expect(namespaced).to be_approved
expect(namespaced).to respond_to(:approve_review)
expect(namespaced).to respond_to(:approve_review!)
namespaced.approve_review!
expect(namespaced).to respond_to(:review_approved?)
expect(namespaced).to be_review_approved
end
it 'denies transitions to other states' do
expect {namespaced.unapprove}.to raise_error(AASM::InvalidTransition)
expect {namespaced.unapprove!}.to raise_error(AASM::InvalidTransition)
namespaced.approve
expect {namespaced.approve}.to raise_error(AASM::InvalidTransition)
expect {namespaced.approve!}.to raise_error(AASM::InvalidTransition)
namespaced.unapprove
expect {namespaced.unapprove_review}.to raise_error(AASM::InvalidTransition)
expect {namespaced.unapprove_review!}.to raise_error(AASM::InvalidTransition)
namespaced.approve_review
expect {namespaced.approve_review}.to raise_error(AASM::InvalidTransition)
expect {namespaced.approve_review!}.to raise_error(AASM::InvalidTransition)
namespaced.unapprove_review
end
it 'defines constants for each state name' do
expect(NamespacedMultipleExample::STATE_UNAPPROVED).to eq(:unapproved)
expect(NamespacedMultipleExample::STATE_APPROVED).to eq(:approved)
expect(NamespacedMultipleExample::STATE_REVIEW_UNAPPROVED).to eq(:unapproved)
expect(NamespacedMultipleExample::STATE_REVIEW_APPROVED).to eq(:approved)
end
end