diff --git a/lib/aasm/base.rb b/lib/aasm/base.rb index 3e16a82..77339d1 100644 --- a/lib/aasm/base.rb +++ b/lib/aasm/base.rb @@ -27,11 +27,19 @@ module AASM configure :enum, nil - if @state_machine.config.no_direct_assignment - @klass.send(:define_method, "#{@state_machine.config.column}=") do |state_name| - raise AASM::NoDirectAssignmentError.new('direct assignment of AASM column has been disabled (see AASM configuration for this class)') + # make sure to raise an error if no_direct_assignment is enabled + # and attribute is directly assigned though + @klass.class_eval %Q( + def #{@state_machine.config.column}=(state_name) + if self.class.aasm.state_machine.config.no_direct_assignment + raise AASM::NoDirectAssignmentError.new( + 'direct assignment of AASM column has been disabled (see AASM configuration for this class)' + ) + else + super + end end - end + ) end # This method is both a getter and a setter diff --git a/spec/models/active_record/localizer_test_model.rb b/spec/models/active_record/localizer_test_model.rb index 1eb3c48..cb83402 100644 --- a/spec/models/active_record/localizer_test_model.rb +++ b/spec/models/active_record/localizer_test_model.rb @@ -1,8 +1,6 @@ class LocalizerTestModel < ActiveRecord::Base include AASM - attr_accessor :aasm_state - aasm do state :opened, :initial => true state :closed diff --git a/spec/unit/persistence/active_record_persistence_spec.rb b/spec/unit/persistence/active_record_persistence_spec.rb index d8df5a3..fc2e486 100644 --- a/spec/unit/persistence/active_record_persistence_spec.rb +++ b/spec/unit/persistence/active_record_persistence_spec.rb @@ -321,6 +321,24 @@ describe "direct assignment" do expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError) expect(obj.aasm_state.to_sym).to eql :pending end + + it 'can be turned off and on again' do + obj = NoDirectAssignment.create + expect(obj.aasm_state.to_sym).to eql :pending + + expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError) + expect(obj.aasm_state.to_sym).to eql :pending + + # allow it temporarily + NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = false + obj.aasm_state = :pending + expect(obj.aasm_state.to_sym).to eql :pending + + # and forbid it again + NoDirectAssignment.aasm.state_machine.config.no_direct_assignment = true + expect {obj.aasm_state = :running}.to raise_error(AASM::NoDirectAssignmentError) + expect(obj.aasm_state.to_sym).to eql :pending + end end # direct assignment describe 'initial states' do