From d59dbbf6b0db2f07a4f0175f6de46aef832ecba5 Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Wed, 5 Nov 2008 11:06:36 -0500 Subject: [PATCH] Allow duplicate state names in subclasses When an AASM including class is subclassed, a shallow copy is made of the StateMachine object. This means that all subclasses share the same states hash and thus the same set of states, which prevents (among other things) different subclasses from using the same state names. Give StateMachine a smart #clone method that copies the states hash and invoke that rather than #dup upon subclassing. --- lib/aasm.rb | 2 +- lib/state_machine.rb | 6 ++++++ spec/unit/aasm_spec.rb | 21 +++++++++++++++------ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/aasm.rb b/lib/aasm.rb index e90e9b5..b5a91ca 100644 --- a/lib/aasm.rb +++ b/lib/aasm.rb @@ -22,7 +22,7 @@ module AASM module ClassMethods def inherited(klass) - AASM::StateMachine[klass] = AASM::StateMachine[self].dup + AASM::StateMachine[klass] = AASM::StateMachine[self].clone super end diff --git a/lib/state_machine.rb b/lib/state_machine.rb index cd98bf0..672aef5 100644 --- a/lib/state_machine.rb +++ b/lib/state_machine.rb @@ -22,6 +22,12 @@ module AASM @config = OpenStruct.new end + def clone + klone = super + klone.states = states.clone + klone + end + def create_state(name, options) @states << AASM::SupportingClasses::State.new(name, options) unless @states.include?(name) end diff --git a/spec/unit/aasm_spec.rb b/spec/unit/aasm_spec.rb index 14ac92e..30cfe87 100644 --- a/spec/unit/aasm_spec.rb +++ b/spec/unit/aasm_spec.rb @@ -70,12 +70,21 @@ describe AASM, '- class level definitions' do end -describe AASM, '- when included' do - it 'should invoke the original inherited callback when subclassed' do - parent = Class.new - parent.should_receive(:inherited) - parent.send(:include, AASM) - child = Class.new(parent) +describe AASM, '- subclassing' do + before(:each) do + @parent = Class.new do + include AASM + end + end + + it 'should invoke the original inherited callback' do + @parent.should_receive(:inherited) + Class.new(@parent) + end + + it 'should have a unique states hash' do + child = Class.new(@parent) + child.aasm_states.equal?(@parent.aasm_states).should be_false end end