aasm 4.6.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/README.md +17 -0
- data/lib/aasm/aasm.rb +17 -1
- data/lib/aasm/base.rb +24 -0
- data/lib/aasm/core/event.rb +16 -4
- data/lib/aasm/core/state.rb +2 -2
- data/lib/aasm/core/transition.rb +2 -2
- data/lib/aasm/persistence/active_record_persistence.rb +18 -7
- data/lib/aasm/version.rb +1 -1
- data/spec/models/callbacks/basic.rb +29 -22
- data/spec/models/foo.rb +27 -13
- data/spec/models/state_machine_with_failed_event.rb +8 -0
- data/spec/models/validator.rb +36 -0
- data/spec/unit/callbacks_spec.rb +176 -31
- data/spec/unit/event_naming_spec.rb +6 -1
- data/spec/unit/persistence/active_record_persistence_spec.rb +65 -0
- metadata +1 -1
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: f758ead4b090ac11ffd00fd7b5a85b5a24dfa626
         | 
| 4 | 
            +
              data.tar.gz: 7e2192786e067726f08fdae1f70341922edf63bb
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f3df7b62a3328455e73356824ceca28663ea789963518730e731078f8d419dbcda1fc20dafe7697563e5e8da5a97fe1409ddda0366b48258c14c14e671b4b855
         | 
| 7 | 
            +
              data.tar.gz: 2a001ca4ce4e3b8452396546201e2506fc467eb5b12ad24dfbd21ed420f20112df5b854e45e2c02211a463f3476ec4e0ce9a587936c082c0200ed4e5bebf6127
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,9 +1,14 @@ | |
| 1 1 | 
             
            # CHANGELOG
         | 
| 2 2 |  | 
| 3 | 
            +
            ## 4.7.0
         | 
| 4 | 
            +
             | 
| 5 | 
            +
             * fix: allow :send as event name (see [issue #257](https://github.com/aasm/aasm/issues/257) for details)
         | 
| 6 | 
            +
             * add new callbacks: transactions, all events, ensure (see [issue #282](https://github.com/aasm/aasm/issues/282) for details, thanks to [@HoyaBoya](https://github.com/HoyaBoya))
         | 
| 7 | 
            +
             | 
| 3 8 | 
             
            ## 4.6.0
         | 
| 4 9 |  | 
| 5 10 | 
             
             * fix: make sure the column is actually present for _ActiveRecord_ enums (see [issue #265](https://github.com/aasm/aasm/issues/265) and [issue #152](https://github.com/aasm/aasm/issues/152) for details, thanks to [@anilmaurya](https://github.com/anilmaurya))
         | 
| 6 | 
            -
            * add generators to configure active_record and mongoid after install (see [issue #261](https://github.com/aasm/aasm/issues/261) for details, thanks to [@anilmaurya](https://github.com/anilmaurya))
         | 
| 11 | 
            +
             * add generators to configure active_record and mongoid after install (see [issue #261](https://github.com/aasm/aasm/issues/261) for details, thanks to [@anilmaurya](https://github.com/anilmaurya))
         | 
| 7 12 |  | 
| 8 13 | 
             
            ## 4.5.2
         | 
| 9 14 |  | 
    
        data/README.md
    CHANGED
    
    | @@ -146,6 +146,7 @@ Here you can see a list of all possible callbacks, together with their order of | |
| 146 146 |  | 
| 147 147 | 
             
            ```ruby
         | 
| 148 148 | 
             
            begin
         | 
| 149 | 
            +
              event           before_all_events
         | 
| 149 150 | 
             
              event           before
         | 
| 150 151 | 
             
              event           guards
         | 
| 151 152 | 
             
              transition      guards
         | 
| @@ -160,8 +161,13 @@ begin | |
| 160 161 | 
             
              old_state       after_exit
         | 
| 161 162 | 
             
              new_state       after_enter
         | 
| 162 163 | 
             
              event           after
         | 
| 164 | 
            +
              event           after_all_events
         | 
| 163 165 | 
             
            rescue
         | 
| 164 166 | 
             
              event           error
         | 
| 167 | 
            +
              event           error_on_all_events
         | 
| 168 | 
            +
            ensure
         | 
| 169 | 
            +
              event           ensure
         | 
| 170 | 
            +
              event           ensure_on_all_events
         | 
| 165 171 | 
             
            end
         | 
| 166 172 | 
             
            ```
         | 
| 167 173 |  | 
| @@ -614,6 +620,17 @@ Since version *3.0.13* AASM supports ActiveRecord transactions. So whenever a tr | |
| 614 620 | 
             
            callback or the state update fails, all changes to any database record are rolled back.
         | 
| 615 621 | 
             
            Mongodb does not support transactions.
         | 
| 616 622 |  | 
| 623 | 
            +
            There are currently 3 transactional callbacks that can be handled on the event, and 2 transactional callbacks for all events.
         | 
| 624 | 
            +
             | 
| 625 | 
            +
            ```ruby
         | 
| 626 | 
            +
              event           before_all_transactions
         | 
| 627 | 
            +
              event           before_transaction
         | 
| 628 | 
            +
              event           aasm_fire_event (within transaction)
         | 
| 629 | 
            +
              event           after_commit (if event successful)
         | 
| 630 | 
            +
              event           after_transaction
         | 
| 631 | 
            +
              event           after_all_transactions
         | 
| 632 | 
            +
            ```
         | 
| 633 | 
            +
             | 
| 617 634 | 
             
            If you want to make sure a depending action happens only after the transaction is committed,
         | 
| 618 635 | 
             
            use the `after_commit` callback along with the auto-save (bang) methods, like this:
         | 
| 619 636 |  | 
    
        data/lib/aasm/aasm.rb
    CHANGED
    
    | @@ -88,6 +88,12 @@ private | |
| 88 88 | 
             
                begin
         | 
| 89 89 | 
             
                  old_state = aasm(state_machine_name).state_object_for_name(aasm(state_machine_name).current_state)
         | 
| 90 90 |  | 
| 91 | 
            +
                  event.fire_global_callbacks(
         | 
| 92 | 
            +
                    :before_all_events,
         | 
| 93 | 
            +
                    self,
         | 
| 94 | 
            +
                    *process_args(event, aasm(state_machine_name).current_state, *args)
         | 
| 95 | 
            +
                  )
         | 
| 96 | 
            +
             | 
| 91 97 | 
             
                  # new event before callback
         | 
| 92 98 | 
             
                  event.fire_callbacks(
         | 
| 93 99 | 
             
                    :before,
         | 
| @@ -110,7 +116,12 @@ private | |
| 110 116 | 
             
                    aasm_failed(state_machine_name, event_name, old_state)
         | 
| 111 117 | 
             
                  end
         | 
| 112 118 | 
             
                rescue StandardError => e
         | 
| 113 | 
            -
                  event.fire_callbacks(:error, self, e, *process_args(event, aasm(state_machine_name).current_state, *args)) || | 
| 119 | 
            +
                  event.fire_callbacks(:error, self, e, *process_args(event, aasm(state_machine_name).current_state, *args)) ||
         | 
| 120 | 
            +
                  event.fire_global_callbacks(:error_on_all_events, self, e, *process_args(event, aasm(state_machine_name).current_state, *args)) ||
         | 
| 121 | 
            +
                  raise(e)
         | 
| 122 | 
            +
                ensure
         | 
| 123 | 
            +
                  event.fire_callbacks(:ensure, self, *process_args(event, aasm(state_machine_name).current_state, *args))
         | 
| 124 | 
            +
                  event.fire_global_callbacks(:ensure_on_all_events, self, *process_args(event, aasm(state_machine_name).current_state, *args))
         | 
| 114 125 | 
             
                end
         | 
| 115 126 | 
             
              end
         | 
| 116 127 |  | 
| @@ -147,6 +158,11 @@ private | |
| 147 158 | 
             
                    self,
         | 
| 148 159 | 
             
                    *process_args(event, old_state.name, *args)
         | 
| 149 160 | 
             
                  )
         | 
| 161 | 
            +
                  event.fire_global_callbacks(
         | 
| 162 | 
            +
                    :after_all_events,
         | 
| 163 | 
            +
                    self,
         | 
| 164 | 
            +
                    *process_args(event, old_state.name, *args)
         | 
| 165 | 
            +
                  )
         | 
| 150 166 |  | 
| 151 167 | 
             
                  self.aasm_event_fired(event.name, old_state.name, aasm(state_machine_name).current_state) if self.respond_to?(:aasm_event_fired)
         | 
| 152 168 | 
             
                else
         | 
    
        data/lib/aasm/base.rb
    CHANGED
    
    | @@ -113,6 +113,30 @@ module AASM | |
| 113 113 | 
             
                  @state_machine.add_global_callbacks(:after_all_transitions, *callbacks, &block)
         | 
| 114 114 | 
             
                end
         | 
| 115 115 |  | 
| 116 | 
            +
                def after_all_transactions(*callbacks, &block)
         | 
| 117 | 
            +
                  @state_machine.add_global_callbacks(:after_all_transactions, *callbacks, &block)
         | 
| 118 | 
            +
                end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                def before_all_transactions(*callbacks, &block)
         | 
| 121 | 
            +
                  @state_machine.add_global_callbacks(:before_all_transactions, *callbacks, &block)
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                def before_all_events(*callbacks, &block)
         | 
| 125 | 
            +
                  @state_machine.add_global_callbacks(:before_all_events, *callbacks, &block)
         | 
| 126 | 
            +
                end
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                def after_all_events(*callbacks, &block)
         | 
| 129 | 
            +
                  @state_machine.add_global_callbacks(:after_all_events, *callbacks, &block)
         | 
| 130 | 
            +
                end
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                def error_on_all_events(*callbacks, &block)
         | 
| 133 | 
            +
                  @state_machine.add_global_callbacks(:error_on_all_events, *callbacks, &block)
         | 
| 134 | 
            +
                end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                def ensure_on_all_events(*callbacks, &block)
         | 
| 137 | 
            +
                  @state_machine.add_global_callbacks(:ensure_on_all_events, *callbacks, &block)
         | 
| 138 | 
            +
                end
         | 
| 139 | 
            +
             | 
| 116 140 | 
             
                def states
         | 
| 117 141 | 
             
                  @state_machine.states
         | 
| 118 142 | 
             
                end
         | 
    
        data/lib/aasm/core/event.rb
    CHANGED
    
    | @@ -13,7 +13,16 @@ module AASM::Core | |
| 13 13 |  | 
| 14 14 | 
             
                  # from aasm4
         | 
| 15 15 | 
             
                  @options = options # QUESTION: .dup ?
         | 
| 16 | 
            -
                  add_options_from_dsl(@options, [ | 
| 16 | 
            +
                  add_options_from_dsl(@options, [
         | 
| 17 | 
            +
                    :after,
         | 
| 18 | 
            +
                    :after_commit,
         | 
| 19 | 
            +
                    :after_transaction,
         | 
| 20 | 
            +
                    :before,
         | 
| 21 | 
            +
                    :before_transaction,
         | 
| 22 | 
            +
                    :ensure,
         | 
| 23 | 
            +
                    :error,
         | 
| 24 | 
            +
                    :success,
         | 
| 25 | 
            +
                  ], &block) if block
         | 
| 17 26 | 
             
                end
         | 
| 18 27 |  | 
| 19 28 | 
             
                # a neutered version of fire - it doesn't actually fire the event, it just
         | 
| @@ -43,6 +52,10 @@ module AASM::Core | |
| 43 52 | 
             
                  @transitions.select { |t| t.to == state }
         | 
| 44 53 | 
             
                end
         | 
| 45 54 |  | 
| 55 | 
            +
                def fire_global_callbacks(callback_name, record, *args)
         | 
| 56 | 
            +
                  invoke_callbacks(state_machine.global_callbacks[callback_name], record, args)
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
             | 
| 46 59 | 
             
                def fire_callbacks(callback_name, record, *args)
         | 
| 47 60 | 
             
                  # strip out the first element in args if it's a valid to_state
         | 
| 48 61 | 
             
                  # #given where we're coming from, this condition implies args not empty
         | 
| @@ -128,8 +141,8 @@ module AASM::Core | |
| 128 141 | 
             
                      unless record.respond_to?(code, true)
         | 
| 129 142 | 
             
                        raise NoMethodError.new("NoMethodError: undefined method `#{code}' for #{record.inspect}:#{record.class}")
         | 
| 130 143 | 
             
                      end
         | 
| 131 | 
            -
                      arity = record. | 
| 132 | 
            -
                      record. | 
| 144 | 
            +
                      arity = record.__send__(:method, code.to_sym).arity
         | 
| 145 | 
            +
                      record.__send__(code, *(arity < 0 ? args : args[0...arity]))
         | 
| 133 146 | 
             
                      true
         | 
| 134 147 |  | 
| 135 148 | 
             
                    when Proc
         | 
| @@ -145,6 +158,5 @@ module AASM::Core | |
| 145 158 | 
             
                      false
         | 
| 146 159 | 
             
                  end
         | 
| 147 160 | 
             
                end
         | 
| 148 | 
            -
             | 
| 149 161 | 
             
              end
         | 
| 150 162 | 
             
            end # AASM
         | 
    
        data/lib/aasm/core/state.rb
    CHANGED
    
    | @@ -70,8 +70,8 @@ module AASM::Core | |
| 70 70 | 
             
                def _fire_callbacks(action, record, args)
         | 
| 71 71 | 
             
                  case action
         | 
| 72 72 | 
             
                    when Symbol, String
         | 
| 73 | 
            -
                      arity = record. | 
| 74 | 
            -
                      record. | 
| 73 | 
            +
                      arity = record.__send__(:method, action.to_sym).arity
         | 
| 74 | 
            +
                      record.__send__(action, *(arity < 0 ? args : args[0...arity]))
         | 
| 75 75 | 
             
                    when Proc
         | 
| 76 76 | 
             
                      arity = action.arity
         | 
| 77 77 | 
             
                      action.call(record, *(arity < 0 ? args : args[0...arity]))
         | 
    
        data/lib/aasm/core/transition.rb
    CHANGED
    
    | @@ -52,8 +52,8 @@ module AASM::Core | |
| 52 52 |  | 
| 53 53 | 
             
                  case code
         | 
| 54 54 | 
             
                  when Symbol, String
         | 
| 55 | 
            -
                    arity = record. | 
| 56 | 
            -
                    arity == 0 ? record. | 
| 55 | 
            +
                    arity = record.__send__(:method, code.to_sym).arity
         | 
| 56 | 
            +
                    arity == 0 ? record.__send__(code) : record.__send__(code, *args)
         | 
| 57 57 | 
             
                  when Proc
         | 
| 58 58 | 
             
                    code.parameters.size == 0 ? record.instance_exec(&code) : record.instance_exec(*args, &code)
         | 
| 59 59 | 
             
                  when Array
         | 
| @@ -129,11 +129,9 @@ module AASM | |
| 129 129 | 
             
                    end
         | 
| 130 130 |  | 
| 131 131 | 
             
                    # Ensures that if the aasm_state column is nil and the record is new
         | 
| 132 | 
            -
                    # then the initial state gets populated  | 
| 132 | 
            +
                    # then the initial state gets populated after initialization
         | 
| 133 133 | 
             
                    #
         | 
| 134 134 | 
             
                    #   foo = Foo.new
         | 
| 135 | 
            -
                    #   foo.aasm_state # => nil
         | 
| 136 | 
            -
                    #   foo.valid?
         | 
| 137 135 | 
             
                    #   foo.aasm_state # => "open" (where :open is the initial state)
         | 
| 138 136 | 
             
                    #
         | 
| 139 137 | 
             
                    #
         | 
| @@ -159,11 +157,24 @@ module AASM | |
| 159 157 | 
             
                    end
         | 
| 160 158 |  | 
| 161 159 | 
             
                    def aasm_fire_event(state_machine_name, name, options, *args, &block)
         | 
| 162 | 
            -
                       | 
| 160 | 
            +
                      event = self.class.aasm(state_machine_name).state_machine.events[name]
         | 
| 161 | 
            +
             | 
| 162 | 
            +
                      if options[:persist]
         | 
| 163 | 
            +
                        event.fire_callbacks(:before_transaction, self, *args)
         | 
| 164 | 
            +
                        event.fire_global_callbacks(:before_all_transactions, self, *args)
         | 
| 165 | 
            +
                      end
         | 
| 163 166 |  | 
| 164 | 
            -
                       | 
| 165 | 
            -
                         | 
| 166 | 
            -
                         | 
| 167 | 
            +
                      begin
         | 
| 168 | 
            +
                        success = options[:persist] ? self.class.transaction(:requires_new => requires_new?(state_machine_name)) { super } : super
         | 
| 169 | 
            +
                        if options[:persist] && success
         | 
| 170 | 
            +
                          event.fire_callbacks(:after_commit, self, *args)
         | 
| 171 | 
            +
                          event.fire_global_callbacks(:after_all_commits, self, *args)
         | 
| 172 | 
            +
                        end
         | 
| 173 | 
            +
                      ensure
         | 
| 174 | 
            +
                        if options[:persist]
         | 
| 175 | 
            +
                          event.fire_callbacks(:after_transaction, self, *args)
         | 
| 176 | 
            +
                          event.fire_global_callbacks(:after_all_transactions, self, *args)
         | 
| 177 | 
            +
                        end
         | 
| 167 178 | 
             
                      end
         | 
| 168 179 |  | 
| 169 180 | 
             
                      success
         | 
    
        data/lib/aasm/version.rb
    CHANGED
    
    
| @@ -18,7 +18,10 @@ module Callbacks | |
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 20 | 
             
                aasm do
         | 
| 21 | 
            -
                   | 
| 21 | 
            +
                  before_all_events       :before_all_events
         | 
| 22 | 
            +
                  after_all_events        :after_all_events
         | 
| 23 | 
            +
                  ensure_on_all_events    :ensure_on_all_events
         | 
| 24 | 
            +
                  after_all_transitions   :after_all_transitions
         | 
| 22 25 |  | 
| 23 26 | 
             
                  state :open, :initial => true,
         | 
| 24 27 | 
             
                    :before_enter => :before_enter_open,
         | 
| @@ -36,11 +39,11 @@ module Callbacks | |
| 36 39 | 
             
                    :exit         => :exit_closed,
         | 
| 37 40 | 
             
                    :after_exit   => :after_exit_closed
         | 
| 38 41 |  | 
| 39 | 
            -
                  event :close, :before => :before_event, :after => :after_event, :guard => :event_guard do
         | 
| 42 | 
            +
                  event :close, :before => :before_event, :after => :after_event, :guard => :event_guard, :ensure => :ensure_event do
         | 
| 40 43 | 
             
                    transitions :to => :closed, :from => [:open], :guard => :transition_guard, :after => :after_transition
         | 
| 41 44 | 
             
                  end
         | 
| 42 45 |  | 
| 43 | 
            -
                  event :open, :before => :before_event, :after => :after_event | 
| 46 | 
            +
                  event :open, :before => :before_event, :after => :after_event  do
         | 
| 44 47 | 
             
                    transitions :to => :open, :from => :closed
         | 
| 45 48 | 
             
                  end
         | 
| 46 49 | 
             
                end
         | 
| @@ -50,29 +53,33 @@ module Callbacks | |
| 50 53 | 
             
                  puts text if @log
         | 
| 51 54 | 
             
                end
         | 
| 52 55 |  | 
| 53 | 
            -
                def aasm_write_state(*args); | 
| 56 | 
            +
                def aasm_write_state(*args);  log('aasm_write_state'); true;  end
         | 
| 57 | 
            +
                def before_enter_open;        log('before_enter_open');       end
         | 
| 58 | 
            +
                def enter_open;               log('enter_open');              end
         | 
| 59 | 
            +
                def before_exit_open;         log('before_exit_open');        end
         | 
| 60 | 
            +
                def after_enter_open;         log('after_enter_open');        end
         | 
| 61 | 
            +
                def exit_open;                log('exit_open');               end
         | 
| 62 | 
            +
                def after_exit_open;          log('after_exit_open');         end
         | 
| 54 63 |  | 
| 55 | 
            -
                def  | 
| 56 | 
            -
                def  | 
| 57 | 
            -
                def  | 
| 58 | 
            -
                def  | 
| 59 | 
            -
                def  | 
| 60 | 
            -
                def  | 
| 64 | 
            +
                def before_enter_closed;      log('before_enter_closed'); end
         | 
| 65 | 
            +
                def enter_closed;             log('enter_closed');        end
         | 
| 66 | 
            +
                def before_exit_closed;       log('before_exit_closed');  end
         | 
| 67 | 
            +
                def exit_closed;              log('exit_closed');         end
         | 
| 68 | 
            +
                def after_enter_closed;       log('after_enter_closed');  end
         | 
| 69 | 
            +
                def after_exit_closed;        log('after_exit_closed');   end
         | 
| 61 70 |  | 
| 62 | 
            -
                def  | 
| 63 | 
            -
                def  | 
| 64 | 
            -
                def before_exit_closed;   log('before_exit_closed');  end
         | 
| 65 | 
            -
                def exit_closed;          log('exit_closed');         end
         | 
| 66 | 
            -
                def after_enter_closed;   log('after_enter_closed');  end
         | 
| 67 | 
            -
                def after_exit_closed;    log('after_exit_closed');   end
         | 
| 71 | 
            +
                def event_guard;              log('event_guard');         !@fail_event_guard;      end
         | 
| 72 | 
            +
                def transition_guard;         log('transition_guard');    !@fail_transition_guard; end
         | 
| 68 73 |  | 
| 69 | 
            -
                def  | 
| 70 | 
            -
                def  | 
| 74 | 
            +
                def after_transition;         log('after_transition');        end
         | 
| 75 | 
            +
                def after_all_transitions;    log('after_all_transitions');   end
         | 
| 71 76 |  | 
| 72 | 
            -
                def  | 
| 73 | 
            -
                def  | 
| 77 | 
            +
                def before_all_events;        log('before_all_events')    end
         | 
| 78 | 
            +
                def before_event;             log('before_event');        end
         | 
| 79 | 
            +
                def after_event;              log('after_event');         end
         | 
| 80 | 
            +
                def after_all_events;         log('after_all_events');    end
         | 
| 74 81 |  | 
| 75 | 
            -
                def  | 
| 76 | 
            -
                def  | 
| 82 | 
            +
                def ensure_event;             log('ensure');              end
         | 
| 83 | 
            +
                def ensure_on_all_events;     log('ensure');              end
         | 
| 77 84 | 
             
              end
         | 
| 78 85 | 
             
            end
         | 
    
        data/spec/models/foo.rb
    CHANGED
    
    | @@ -1,16 +1,19 @@ | |
| 1 | 
            -
             | 
| 2 | 
            -
               | 
| 3 | 
            -
             | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 1 | 
            +
            module Fooable
         | 
| 2 | 
            +
              def self.included(base)
         | 
| 3 | 
            +
                base.class_eval do
         | 
| 4 | 
            +
                  aasm do
         | 
| 5 | 
            +
                    state :open, :initial => true, :before_exit => :before_exit
         | 
| 6 | 
            +
                    state :closed, :before_enter => :before_enter
         | 
| 7 | 
            +
                    state :final
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    event :close, :success => :success_callback do
         | 
| 10 | 
            +
                      transitions :from => [:open], :to => [:closed]
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    event :null do
         | 
| 14 | 
            +
                      transitions :from => [:open], :to => [:closed, :final], :guard => :always_false
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
                  end
         | 
| 14 17 | 
             
                end
         | 
| 15 18 | 
             
              end
         | 
| 16 19 |  | 
| @@ -23,10 +26,21 @@ class Foo | |
| 23 26 |  | 
| 24 27 | 
             
              def before_enter
         | 
| 25 28 | 
             
              end
         | 
| 29 | 
            +
             | 
| 26 30 | 
             
              def before_exit
         | 
| 27 31 | 
             
              end
         | 
| 28 32 | 
             
            end
         | 
| 29 33 |  | 
| 34 | 
            +
            class Foo
         | 
| 35 | 
            +
              include AASM
         | 
| 36 | 
            +
              include Fooable
         | 
| 37 | 
            +
            end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            class FooGlobal
         | 
| 40 | 
            +
              include AASM
         | 
| 41 | 
            +
              include Fooable
         | 
| 42 | 
            +
            end
         | 
| 43 | 
            +
             | 
| 30 44 | 
             
            class FooTwo < Foo
         | 
| 31 45 | 
             
              include AASM
         | 
| 32 46 | 
             
              aasm do
         | 
| @@ -4,9 +4,17 @@ class StateMachineWithFailedEvent | |
| 4 4 | 
             
              aasm do
         | 
| 5 5 | 
             
                state :init, :initial => true
         | 
| 6 6 | 
             
                state :failed
         | 
| 7 | 
            +
                state :sent
         | 
| 7 8 |  | 
| 8 9 | 
             
                event :failed do
         | 
| 9 10 | 
             
                  transitions :from => :init, :to => :failed
         | 
| 10 11 | 
             
                end
         | 
| 12 | 
            +
                event :send, :before => :callback do
         | 
| 13 | 
            +
                  transitions :from => :init, :to => :sent
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              def callback
         | 
| 18 | 
            +
                true
         | 
| 11 19 | 
             
              end
         | 
| 12 20 | 
             
            end
         | 
    
        data/spec/models/validator.rb
    CHANGED
    
    | @@ -1,23 +1,51 @@ | |
| 1 1 | 
             
            require 'active_record'
         | 
| 2 2 |  | 
| 3 3 | 
             
            class Validator < ActiveRecord::Base
         | 
| 4 | 
            +
              attr_accessor :after_all_transactions_performed,
         | 
| 5 | 
            +
                :after_transaction_performed_on_fail,
         | 
| 6 | 
            +
                :after_transaction_performed_on_run,
         | 
| 7 | 
            +
                :before_all_transactions_performed,
         | 
| 8 | 
            +
                :before_transaction_performed_on_fail,
         | 
| 9 | 
            +
                :before_transaction_performed_on_run
         | 
| 4 10 |  | 
| 5 11 | 
             
              include AASM
         | 
| 12 | 
            +
             | 
| 6 13 | 
             
              aasm :column => :status do
         | 
| 14 | 
            +
                before_all_transactions :before_all_transactions
         | 
| 15 | 
            +
                after_all_transactions  :after_all_transactions
         | 
| 16 | 
            +
             | 
| 7 17 | 
             
                state :sleeping, :initial => true
         | 
| 8 18 | 
             
                state :running
         | 
| 9 19 | 
             
                state :failed, :after_enter => :fail
         | 
| 10 20 |  | 
| 11 21 | 
             
                event :run, :after_commit => :change_name! do
         | 
| 22 | 
            +
                  after_transaction do
         | 
| 23 | 
            +
                    @after_transaction_performed_on_run = true
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  before_transaction do
         | 
| 27 | 
            +
                    @before_transaction_performed_on_run = true
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 12 30 | 
             
                  transitions :to => :running, :from => :sleeping
         | 
| 13 31 | 
             
                end
         | 
| 32 | 
            +
             | 
| 14 33 | 
             
                event :sleep do
         | 
| 15 34 | 
             
                  after_commit do |name|
         | 
| 16 35 | 
             
                    change_name_on_sleep name
         | 
| 17 36 | 
             
                  end
         | 
| 18 37 | 
             
                  transitions :to => :sleeping, :from => :running
         | 
| 19 38 | 
             
                end
         | 
| 39 | 
            +
             | 
| 20 40 | 
             
                event :fail do
         | 
| 41 | 
            +
                  after_transaction do
         | 
| 42 | 
            +
                    @after_transaction_performed_on_fail = true
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  before_transaction do
         | 
| 46 | 
            +
                    @before_transaction_performed_on_fail = true
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 21 49 | 
             
                  transitions :to => :failed, :from => [:sleeping, :running]
         | 
| 22 50 | 
             
                end
         | 
| 23 51 | 
             
              end
         | 
| @@ -37,6 +65,14 @@ class Validator < ActiveRecord::Base | |
| 37 65 | 
             
              def fail
         | 
| 38 66 | 
             
                raise StandardError.new('failed on purpose')
         | 
| 39 67 | 
             
              end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
              def after_all_transactions
         | 
| 70 | 
            +
                @after_all_transactions_performed = true
         | 
| 71 | 
            +
              end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
              def before_all_transactions
         | 
| 74 | 
            +
                @before_all_transactions_performed = true
         | 
| 75 | 
            +
              end
         | 
| 40 76 | 
             
            end
         | 
| 41 77 |  | 
| 42 78 | 
             
            class MultipleValidator < ActiveRecord::Base
         | 
    
        data/spec/unit/callbacks_spec.rb
    CHANGED
    
    | @@ -1,6 +1,65 @@ | |
| 1 1 | 
             
            require 'spec_helper'
         | 
| 2 2 | 
             
            Dir[File.dirname(__FILE__) + "/../models/callbacks/*.rb"].sort.each { |f| require File.expand_path(f) }
         | 
| 3 3 |  | 
| 4 | 
            +
            shared_examples 'an implemented callback that accepts error' do
         | 
| 5 | 
            +
              context 'with callback defined' do
         | 
| 6 | 
            +
                it "should run error_callback if an exception is raised" do
         | 
| 7 | 
            +
                  aasm_model.class.send(:define_method, callback_name) do |e|
         | 
| 8 | 
            +
                    @data = [e]
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  allow(aasm_model).to receive(:before_enter).and_raise(e = StandardError.new)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  aasm_model.safe_close!
         | 
| 14 | 
            +
                  expect(aasm_model.data).to eql [e]
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                it "should run error_callback without parameters if callback does not support any" do
         | 
| 18 | 
            +
                  aasm_model.class.send(:define_method, callback_name) do |e|
         | 
| 19 | 
            +
                    @data = []
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  allow(aasm_model).to receive(:before_enter).and_raise(e = StandardError.new)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  aasm_model.safe_close!('arg1', 'arg2')
         | 
| 25 | 
            +
                  expect(aasm_model.data).to eql []
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                it "should run error_callback with parameters if callback supports them" do
         | 
| 29 | 
            +
                  aasm_model.class.send(:define_method, callback_name) do |e, arg1, arg2|
         | 
| 30 | 
            +
                    @data = [arg1, arg2]
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  allow(aasm_model).to receive(:before_enter).and_raise(e = StandardError.new)
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  aasm_model.safe_close!('arg1', 'arg2')
         | 
| 36 | 
            +
                  expect(aasm_model.data).to eql ['arg1', 'arg2']
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            shared_examples 'an implemented callback' do
         | 
| 42 | 
            +
              context 'with callback defined' do
         | 
| 43 | 
            +
                it 'should run callback without parameters if callback does not support any' do
         | 
| 44 | 
            +
                  aasm_model.class.send(:define_method, callback_name) do
         | 
| 45 | 
            +
                    @data = ['callback-was-called']
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  aasm_model.safe_close!
         | 
| 49 | 
            +
                  expect(aasm_model.data).to eql ['callback-was-called']
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                it 'should run callback with parameters if callback supports them' do
         | 
| 53 | 
            +
                  aasm_model.class.send(:define_method, callback_name) do |arg1, arg2|
         | 
| 54 | 
            +
                    @data = [arg1, arg2]
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                  aasm_model.safe_close!('arg1', 'arg2')
         | 
| 58 | 
            +
                  expect(aasm_model.data).to eql ['arg1', 'arg2']
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
            end
         | 
| 62 | 
            +
             | 
| 4 63 | 
             
            describe 'callbacks for the new DSL' do
         | 
| 5 64 |  | 
| 6 65 | 
             
              it "be called in order" do
         | 
| @@ -10,6 +69,7 @@ describe 'callbacks for the new DSL' do | |
| 10 69 | 
             
                callback.aasm.current_state
         | 
| 11 70 |  | 
| 12 71 | 
             
                unless show_debug_log
         | 
| 72 | 
            +
                  expect(callback).to receive(:before_all_events).once.ordered
         | 
| 13 73 | 
             
                  expect(callback).to receive(:before_event).once.ordered
         | 
| 14 74 | 
             
                  expect(callback).to receive(:event_guard).once.ordered.and_return(true)
         | 
| 15 75 | 
             
                  expect(callback).to receive(:transition_guard).once.ordered.and_return(true)
         | 
| @@ -25,6 +85,9 @@ describe 'callbacks for the new DSL' do | |
| 25 85 | 
             
                  expect(callback).to receive(:after_exit_open).once.ordered                    # these should be after the state changes
         | 
| 26 86 | 
             
                  expect(callback).to receive(:after_enter_closed).once.ordered
         | 
| 27 87 | 
             
                  expect(callback).to receive(:after_event).once.ordered
         | 
| 88 | 
            +
                  expect(callback).to receive(:after_all_events).once.ordered
         | 
| 89 | 
            +
                  expect(callback).to receive(:ensure_event).once.ordered
         | 
| 90 | 
            +
                  expect(callback).to receive(:ensure_on_all_events).once.ordered
         | 
| 28 91 | 
             
                end
         | 
| 29 92 |  | 
| 30 93 | 
             
                # puts "------- close!"
         | 
| @@ -35,11 +98,13 @@ describe 'callbacks for the new DSL' do | |
| 35 98 | 
             
                callback = Callbacks::Basic.new(:log => false)
         | 
| 36 99 | 
             
                callback.aasm.current_state
         | 
| 37 100 |  | 
| 101 | 
            +
                expect(callback).to receive(:before_all_events).once.ordered
         | 
| 38 102 | 
             
                expect(callback).to receive(:before_event).once.ordered
         | 
| 39 103 | 
             
                expect(callback).to receive(:event_guard).once.ordered.and_return(false)
         | 
| 40 104 | 
             
                expect(callback).to_not receive(:transition_guard)
         | 
| 41 105 | 
             
                expect(callback).to_not receive(:before_exit_open)
         | 
| 42 106 | 
             
                expect(callback).to_not receive(:exit_open)
         | 
| 107 | 
            +
                expect(callback).to_not receive(:after_all_transitions)
         | 
| 43 108 | 
             
                expect(callback).to_not receive(:after_transition)
         | 
| 44 109 | 
             
                expect(callback).to_not receive(:before_enter_closed)
         | 
| 45 110 | 
             
                expect(callback).to_not receive(:enter_closed)
         | 
| @@ -47,6 +112,9 @@ describe 'callbacks for the new DSL' do | |
| 47 112 | 
             
                expect(callback).to_not receive(:after_exit_open)
         | 
| 48 113 | 
             
                expect(callback).to_not receive(:after_enter_closed)
         | 
| 49 114 | 
             
                expect(callback).to_not receive(:after_event)
         | 
| 115 | 
            +
                expect(callback).to_not receive(:after_all_events)
         | 
| 116 | 
            +
                expect(callback).to receive(:ensure_event).once.ordered
         | 
| 117 | 
            +
                expect(callback).to receive(:ensure_on_all_events).once.ordered
         | 
| 50 118 |  | 
| 51 119 | 
             
                expect {
         | 
| 52 120 | 
             
                  callback.close!
         | 
| @@ -72,11 +140,13 @@ describe 'callbacks for the new DSL' do | |
| 72 140 | 
             
                  callback.aasm.current_state
         | 
| 73 141 |  | 
| 74 142 | 
             
                  unless show_debug_log
         | 
| 143 | 
            +
                    expect(callback).to receive(:before_all_events).once.ordered
         | 
| 75 144 | 
             
                    expect(callback).to receive(:before_event).once.ordered
         | 
| 76 145 | 
             
                    expect(callback).to receive(:event_guard).once.ordered.and_return(true)
         | 
| 77 146 | 
             
                    expect(callback).to receive(:transition_guard).once.ordered.and_return(false)
         | 
| 78 147 | 
             
                    expect(callback).to_not receive(:before_exit_open)
         | 
| 79 148 | 
             
                    expect(callback).to_not receive(:exit_open)
         | 
| 149 | 
            +
                    expect(callback).to_not receive(:after_all_transitions)
         | 
| 80 150 | 
             
                    expect(callback).to_not receive(:after_transition)
         | 
| 81 151 | 
             
                    expect(callback).to_not receive(:before_enter_closed)
         | 
| 82 152 | 
             
                    expect(callback).to_not receive(:enter_closed)
         | 
| @@ -84,6 +154,9 @@ describe 'callbacks for the new DSL' do | |
| 84 154 | 
             
                    expect(callback).to_not receive(:after_exit_open)
         | 
| 85 155 | 
             
                    expect(callback).to_not receive(:after_enter_closed)
         | 
| 86 156 | 
             
                    expect(callback).to_not receive(:after_event)
         | 
| 157 | 
            +
                    expect(callback).to_not receive(:after_all_events)
         | 
| 158 | 
            +
                    expect(callback).to receive(:ensure_event).once.ordered
         | 
| 159 | 
            +
                    expect(callback).to receive(:ensure_on_all_events).once.ordered
         | 
| 87 160 | 
             
                  end
         | 
| 88 161 |  | 
| 89 162 | 
             
                  expect {
         | 
| @@ -201,49 +274,50 @@ describe 'event callbacks' do | |
| 201 274 | 
             
                  @foo = Foo.new
         | 
| 202 275 | 
             
                end
         | 
| 203 276 |  | 
| 204 | 
            -
                 | 
| 205 | 
            -
                   | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
                    end
         | 
| 209 | 
            -
             | 
| 210 | 
            -
                    allow(@foo).to receive(:before_enter).and_raise(e = StandardError.new)
         | 
| 211 | 
            -
             | 
| 212 | 
            -
                    @foo.safe_close!
         | 
| 213 | 
            -
                    expect(@foo.data).to eql [e]
         | 
| 214 | 
            -
                  end
         | 
| 277 | 
            +
                it_behaves_like 'an implemented callback that accepts error' do
         | 
| 278 | 
            +
                  let(:aasm_model) { @foo }
         | 
| 279 | 
            +
                  let(:callback_name) { :error_callback }
         | 
| 280 | 
            +
                end
         | 
| 215 281 |  | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 282 | 
            +
                it "should raise NoMethodError if exception is raised and error_callback is declared but not defined" do
         | 
| 283 | 
            +
                  allow(@foo).to receive(:before_enter).and_raise(StandardError)
         | 
| 284 | 
            +
                  expect{@foo.safe_close!}.to raise_error(NoMethodError)
         | 
| 285 | 
            +
                end
         | 
| 220 286 |  | 
| 221 | 
            -
             | 
| 287 | 
            +
                it "should propagate an error if no error callback is declared" do
         | 
| 288 | 
            +
                  allow(@foo).to receive(:before_enter).and_raise("Cannot enter safe")
         | 
| 289 | 
            +
                  expect{@foo.close!}.to raise_error(StandardError, "Cannot enter safe")
         | 
| 290 | 
            +
                end
         | 
| 291 | 
            +
              end
         | 
| 222 292 |  | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
                   | 
| 293 | 
            +
              describe 'with an ensure callback defined' do
         | 
| 294 | 
            +
                before do
         | 
| 295 | 
            +
                  class Foo
         | 
| 296 | 
            +
                    # this hack is needed to allow testing of parameters, since RSpec
         | 
| 297 | 
            +
                    # destroys a method's arity when mocked
         | 
| 298 | 
            +
                    attr_accessor :data
         | 
| 226 299 |  | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 229 | 
            -
             | 
| 300 | 
            +
                    aasm do
         | 
| 301 | 
            +
                      event :safe_close, :success => :success_callback, :ensure => :ensure_callback do
         | 
| 302 | 
            +
                        transitions :to => :closed, :from => [:open]
         | 
| 303 | 
            +
                      end
         | 
| 230 304 | 
             
                    end
         | 
| 305 | 
            +
                  end
         | 
| 231 306 |  | 
| 232 | 
            -
             | 
| 307 | 
            +
                  @foo = Foo.new
         | 
| 308 | 
            +
                end
         | 
| 233 309 |  | 
| 234 | 
            -
             | 
| 235 | 
            -
             | 
| 236 | 
            -
                   | 
| 310 | 
            +
                it_behaves_like 'an implemented callback' do
         | 
| 311 | 
            +
                  let(:aasm_model) { @foo }
         | 
| 312 | 
            +
                  let(:callback_name) { :ensure_callback }
         | 
| 237 313 | 
             
                end
         | 
| 238 314 |  | 
| 239 | 
            -
                it "should raise NoMethodError if  | 
| 240 | 
            -
                  allow(@foo).to receive(:before_enter).and_raise(StandardError)
         | 
| 315 | 
            +
                it "should raise NoMethodError if ensure_callback is declared but not defined" do
         | 
| 241 316 | 
             
                  expect{@foo.safe_close!}.to raise_error(NoMethodError)
         | 
| 242 317 | 
             
                end
         | 
| 243 318 |  | 
| 244 | 
            -
                it "should  | 
| 245 | 
            -
             | 
| 246 | 
            -
                    expect{@foo.close!}.to raise_error(StandardError, "Cannot enter safe")
         | 
| 319 | 
            +
                it "should not raise any error if no ensure_callback is declared" do
         | 
| 320 | 
            +
                  expect{@foo.close!}.to_not raise_error
         | 
| 247 321 | 
             
                end
         | 
| 248 322 | 
             
              end
         | 
| 249 323 |  | 
| @@ -292,5 +366,76 @@ describe 'event callbacks' do | |
| 292 366 | 
             
                  @foo.close!
         | 
| 293 367 | 
             
                end
         | 
| 294 368 | 
             
              end
         | 
| 369 | 
            +
            end
         | 
| 370 | 
            +
             | 
| 371 | 
            +
            describe 'global error_on_all_events_callback callbacks' do
         | 
| 372 | 
            +
              describe "with an error_on_all_events" do
         | 
| 373 | 
            +
                before do
         | 
| 374 | 
            +
                  class FooGlobal
         | 
| 375 | 
            +
                    # this hack is needed to allow testing of parameters, since RSpec
         | 
| 376 | 
            +
                    # destroys a method's arity when mocked
         | 
| 377 | 
            +
                    attr_accessor :data
         | 
| 378 | 
            +
             | 
| 379 | 
            +
                    aasm do
         | 
| 380 | 
            +
                      error_on_all_events  :error_on_all_events_callback
         | 
| 381 | 
            +
             | 
| 382 | 
            +
                      event :safe_close do
         | 
| 383 | 
            +
                        transitions :to => :closed, :from => [:open]
         | 
| 384 | 
            +
                      end
         | 
| 385 | 
            +
                    end
         | 
| 386 | 
            +
                  end
         | 
| 387 | 
            +
             | 
| 388 | 
            +
                  @foo = FooGlobal.new
         | 
| 389 | 
            +
                end
         | 
| 390 | 
            +
             | 
| 391 | 
            +
                it_behaves_like 'an implemented callback that accepts error' do
         | 
| 392 | 
            +
                  let(:aasm_model) { @foo }
         | 
| 393 | 
            +
                  let(:callback_name) { :error_on_all_events_callback }
         | 
| 394 | 
            +
                end
         | 
| 395 | 
            +
             | 
| 396 | 
            +
                it "should raise NoMethodError if exception is raised and error_callback is declared but not defined" do
         | 
| 397 | 
            +
                  allow(@foo).to receive(:before_enter).and_raise(StandardError)
         | 
| 398 | 
            +
                  expect{@foo.safe_close!}.to raise_error(NoMethodError)
         | 
| 399 | 
            +
                end
         | 
| 295 400 |  | 
| 401 | 
            +
                it "should raise NoMethodError if no error callback is declared" do
         | 
| 402 | 
            +
                  allow(@foo).to receive(:before_enter).and_raise("Cannot enter safe")
         | 
| 403 | 
            +
                  expect{@foo.close!}.to raise_error(NoMethodError)
         | 
| 404 | 
            +
                end
         | 
| 405 | 
            +
              end
         | 
| 406 | 
            +
            end
         | 
| 407 | 
            +
             | 
| 408 | 
            +
            describe 'global ensure_on_all_events_callback callbacks' do
         | 
| 409 | 
            +
              describe "with an ensure_on_all_events" do
         | 
| 410 | 
            +
                before do
         | 
| 411 | 
            +
                  class FooGlobal
         | 
| 412 | 
            +
                    # this hack is needed to allow testing of parameters, since RSpec
         | 
| 413 | 
            +
                    # destroys a method's arity when mocked
         | 
| 414 | 
            +
                    attr_accessor :data
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                    aasm do
         | 
| 417 | 
            +
                      ensure_on_all_events  :ensure_on_all_events_callback
         | 
| 418 | 
            +
             | 
| 419 | 
            +
                      event :safe_close do
         | 
| 420 | 
            +
                        transitions :to => :closed, :from => [:open]
         | 
| 421 | 
            +
                      end
         | 
| 422 | 
            +
                    end
         | 
| 423 | 
            +
                  end
         | 
| 424 | 
            +
             | 
| 425 | 
            +
                  @foo = FooGlobal.new
         | 
| 426 | 
            +
                end
         | 
| 427 | 
            +
             | 
| 428 | 
            +
                it_behaves_like 'an implemented callback' do
         | 
| 429 | 
            +
                  let(:aasm_model) { @foo }
         | 
| 430 | 
            +
                  let(:callback_name) { :ensure_on_all_events_callback }
         | 
| 431 | 
            +
                end
         | 
| 432 | 
            +
             | 
| 433 | 
            +
                it "should raise NoMethodError if ensure_on_all_events callback is declared but not defined" do
         | 
| 434 | 
            +
                  expect{@foo.safe_close!}.to raise_error(NoMethodError)
         | 
| 435 | 
            +
                end
         | 
| 436 | 
            +
             | 
| 437 | 
            +
                it "should raise NoMethodError if no ensure_on_all_events callback is declared" do
         | 
| 438 | 
            +
                  expect{@foo.close!}.to raise_error(NoMethodError)
         | 
| 439 | 
            +
                end
         | 
| 440 | 
            +
              end
         | 
| 296 441 | 
             
            end
         | 
| @@ -5,7 +5,12 @@ describe "event naming" do | |
| 5 5 |  | 
| 6 6 | 
             
              it "allows an event of failed without blowing the stack aka stack level too deep" do
         | 
| 7 7 | 
             
                state_machine.failed
         | 
| 8 | 
            -
             | 
| 9 8 | 
             
                expect { state_machine.failed }.to raise_error(AASM::InvalidTransition)
         | 
| 10 9 | 
             
              end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              it "allows send as event name" do
         | 
| 12 | 
            +
                expect(state_machine.aasm.current_state).to eq :init
         | 
| 13 | 
            +
                state_machine.send
         | 
| 14 | 
            +
                expect(state_machine.aasm.current_state).to eq :sent
         | 
| 15 | 
            +
              end
         | 
| 11 16 | 
             
            end
         | 
| @@ -494,7 +494,72 @@ describe 'transitions with persistence' do | |
| 494 494 | 
             
                    expect(validator).to be_running
         | 
| 495 495 | 
             
                    expect(validator.name).to eq("name")
         | 
| 496 496 | 
             
                  end
         | 
| 497 | 
            +
                end
         | 
| 497 498 |  | 
| 499 | 
            +
                describe 'before and after transaction callbacks' do
         | 
| 500 | 
            +
                  [:after, :before].each do |event_type|
         | 
| 501 | 
            +
                    describe "#{event_type}_transaction callback" do
         | 
| 502 | 
            +
                      it "should fire :#{event_type}_transaction if transaction was successful" do
         | 
| 503 | 
            +
                        validator = Validator.create(:name => 'name')
         | 
| 504 | 
            +
                        expect(validator).to be_sleeping
         | 
| 505 | 
            +
             | 
| 506 | 
            +
                        expect { validator.run! }.to change { validator.send("#{event_type}_transaction_performed_on_run") }.from(nil).to(true)
         | 
| 507 | 
            +
                        expect(validator).to be_running
         | 
| 508 | 
            +
                      end
         | 
| 509 | 
            +
             | 
| 510 | 
            +
                      it "should fire :#{event_type}_transaction if transaction failed" do
         | 
| 511 | 
            +
                        validator = Validator.create(:name => 'name')
         | 
| 512 | 
            +
                        expect do
         | 
| 513 | 
            +
                          begin
         | 
| 514 | 
            +
                            validator.fail!
         | 
| 515 | 
            +
                          rescue => ignored
         | 
| 516 | 
            +
                          end
         | 
| 517 | 
            +
                        end.to change { validator.send("#{event_type}_transaction_performed_on_fail") }.from(nil).to(true)
         | 
| 518 | 
            +
                        expect(validator).to_not be_running
         | 
| 519 | 
            +
                      end
         | 
| 520 | 
            +
             | 
| 521 | 
            +
                      it "should not fire :#{event_type}_transaction if not saving" do
         | 
| 522 | 
            +
                        validator = Validator.create(:name => 'name')
         | 
| 523 | 
            +
                        expect(validator).to be_sleeping
         | 
| 524 | 
            +
                        expect { validator.run }.to_not change { validator.send("#{event_type}_transaction_performed_on_run") }
         | 
| 525 | 
            +
                        expect(validator).to be_running
         | 
| 526 | 
            +
                        expect(validator.name).to eq("name")
         | 
| 527 | 
            +
                      end
         | 
| 528 | 
            +
                    end
         | 
| 529 | 
            +
                  end
         | 
| 530 | 
            +
                end
         | 
| 531 | 
            +
             | 
| 532 | 
            +
                describe 'before and after all transactions callbacks' do
         | 
| 533 | 
            +
                  [:after, :before].each do |event_type|
         | 
| 534 | 
            +
                    describe "#{event_type}_all_transactions callback" do
         | 
| 535 | 
            +
                      it "should fire :#{event_type}_all_transactions if transaction was successful" do
         | 
| 536 | 
            +
                        validator = Validator.create(:name => 'name')
         | 
| 537 | 
            +
                        expect(validator).to be_sleeping
         | 
| 538 | 
            +
             | 
| 539 | 
            +
                        expect { validator.run! }.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
         | 
| 540 | 
            +
                        expect(validator).to be_running
         | 
| 541 | 
            +
                      end
         | 
| 542 | 
            +
             | 
| 543 | 
            +
                      it "should fire :#{event_type}_all_transactions if transaction failed" do
         | 
| 544 | 
            +
                        validator = Validator.create(:name => 'name')
         | 
| 545 | 
            +
                        expect do
         | 
| 546 | 
            +
                          begin
         | 
| 547 | 
            +
                            validator.fail!
         | 
| 548 | 
            +
                          rescue => ignored
         | 
| 549 | 
            +
                          end
         | 
| 550 | 
            +
                        end.to change { validator.send("#{event_type}_all_transactions_performed") }.from(nil).to(true)
         | 
| 551 | 
            +
                        expect(validator).to_not be_running
         | 
| 552 | 
            +
                      end
         | 
| 553 | 
            +
             | 
| 554 | 
            +
                      it "should not fire :#{event_type}_all_transactions if not saving" do
         | 
| 555 | 
            +
                        validator = Validator.create(:name => 'name')
         | 
| 556 | 
            +
                        expect(validator).to be_sleeping
         | 
| 557 | 
            +
                        expect { validator.run }.to_not change { validator.send("#{event_type}_all_transactions_performed") }
         | 
| 558 | 
            +
                        expect(validator).to be_running
         | 
| 559 | 
            +
                        expect(validator.name).to eq("name")
         | 
| 560 | 
            +
                      end
         | 
| 561 | 
            +
                    end
         | 
| 562 | 
            +
                  end
         | 
| 498 563 | 
             
                end
         | 
| 499 564 |  | 
| 500 565 | 
             
                context "when not persisting" do
         |