state_machines-audit_trail 1.0.0 → 2.0.2
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 +5 -5
- data/.gitignore +2 -1
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +30 -4
- data/Appraisals +16 -0
- data/README.md +30 -8
- data/Rakefile +7 -1
- data/gemfiles/rails_5.0.gemfile +9 -0
- data/gemfiles/rails_5.1.gemfile +8 -0
- data/gemfiles/rails_5.2.gemfile +8 -0
- data/gemfiles/rails_6.0.gemfile +8 -0
- data/gemfiles/rails_edge.gemfile +10 -0
- data/lib/state_machines-audit_trail.rb +1 -0
- data/lib/state_machines/audit_trail/backend.rb +29 -8
- data/lib/state_machines/audit_trail/backend/active_record.rb +4 -6
- data/lib/state_machines/audit_trail/transition_auditing.rb +8 -4
- data/lib/state_machines/audit_trail/version.rb +1 -1
- data/lib/state_machines/audit_trail_generator.rb +1 -0
- data/spec/helpers/active_record.rb +88 -25
- data/spec/helpers/mongoid.rb +3 -0
- data/spec/helpers/mongoid.yml +1 -1
- data/spec/lib/state_machines/audit_trail/backend/active_record_spec.rb +83 -20
- data/spec/lib/state_machines/audit_trail/backend/mongoid_spec.rb +98 -98
- data/spec/lib/state_machines/audit_trail_generator_spec.rb +2 -2
- data/state_machines-audit_trail.gemspec +10 -5
- metadata +32 -11
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 2 | 
            +
            SHA256:
         | 
| 3 | 
            +
              metadata.gz: fa9c1aad624d9dad005c50ab44eb5522908b1790490f6e8b1eacc1b05261a7e3
         | 
| 4 | 
            +
              data.tar.gz: 9bcb723941ab88d56534181ad6be0c147de7262ee408c2a5607a77bd146b94e2
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ffaacbb29036d844d7a25d72da512906bee8d7a646e63b42b68f3f99bfcd7ff572e33177b84cf85ef079cb284dc2667611ce22b40835d524f065fdfb76f7926f
         | 
| 7 | 
            +
              data.tar.gz: 15cf000aea32b80c3f0cf675fe9cad34574ce127d4328c3faea9f70b62e7d35550b67ef62ed9209000bf46c84e949ccec27821ba2d90861cfb075c43ae616a76
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.ruby-gemset
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            state_machines-audit_trail
         | 
    
        data/.ruby-version
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            2.3.1
         | 
    
        data/.travis.yml
    CHANGED
    
    | @@ -1,17 +1,43 @@ | |
| 1 1 | 
             
            language: ruby
         | 
| 2 | 
            -
            sudo: false
         | 
| 3 2 | 
             
            cache: bundler
         | 
| 4 3 |  | 
| 5 4 | 
             
            script: "bundle exec rake"
         | 
| 6 5 |  | 
| 7 6 | 
             
            services: mongodb
         | 
| 8 7 | 
             
            rvm:
         | 
| 9 | 
            -
              - 2.1
         | 
| 10 | 
            -
              - 2.0.0
         | 
| 11 8 | 
             
              - 2.2
         | 
| 9 | 
            +
              - 2.3
         | 
| 10 | 
            +
              - 2.4
         | 
| 11 | 
            +
              - 2.5
         | 
| 12 | 
            +
              - 2.6
         | 
| 13 | 
            +
              - 2.7
         | 
| 14 | 
            +
              - ruby-head
         | 
| 15 | 
            +
              - jruby-head
         | 
| 12 16 | 
             
              - jruby
         | 
| 13 17 | 
             
              - rbx-2
         | 
| 18 | 
            +
            gemfile:
         | 
| 19 | 
            +
              - gemfiles/rails_5.0.gemfile
         | 
| 20 | 
            +
              - gemfiles/rails_5.1.gemfile
         | 
| 21 | 
            +
              - gemfiles/rails_5.2.gemfile
         | 
| 22 | 
            +
              - gemfiles/rails_6.0.gemfile
         | 
| 23 | 
            +
              - gemfiles/rails_edge.gemfile
         | 
| 14 24 | 
             
            matrix:
         | 
| 25 | 
            +
              exclude:
         | 
| 26 | 
            +
                - rvm: 2.2
         | 
| 27 | 
            +
                  gemfile: gemfiles/rails_6.0.gemfile
         | 
| 28 | 
            +
                - rvm: 2.3
         | 
| 29 | 
            +
                  gemfile: gemfiles/rails_6.0.gemfile
         | 
| 30 | 
            +
                - rvm: 2.4
         | 
| 31 | 
            +
                  gemfile: gemfiles/rails_6.0.gemfile
         | 
| 32 | 
            +
                - rvm: 2.2
         | 
| 33 | 
            +
                  gemfile: gemfiles/rails_edge.gemfile
         | 
| 34 | 
            +
                - rvm: 2.3
         | 
| 35 | 
            +
                  gemfile: gemfiles/rails_edge.gemfile
         | 
| 36 | 
            +
                - rvm: 2.4
         | 
| 37 | 
            +
                  gemfile: gemfiles/rails_edge.gemfile
         | 
| 15 38 | 
             
              allow_failures:
         | 
| 16 39 | 
             
                - rvm: rbx-2
         | 
| 17 | 
            -
                - rvm:  | 
| 40 | 
            +
                - rvm: ruby-head
         | 
| 41 | 
            +
                - rvm: jruby-head
         | 
| 42 | 
            +
                - gemfile: gemfiles/rails_edge.gemfile
         | 
| 43 | 
            +
             | 
    
        data/Appraisals
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            appraise 'rails_5.0' do
         | 
| 2 | 
            +
              gem 'activerecord', '~> 5.0'
         | 
| 3 | 
            +
              gem 'activemodel', '~> 5.0'
         | 
| 4 | 
            +
            end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            appraise 'rails_5.1' do
         | 
| 7 | 
            +
              gem 'activerecord', '~> 5.1'
         | 
| 8 | 
            +
              gem 'activemodel', '~> 5.1'
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            appraise 'rails_edge' do
         | 
| 12 | 
            +
              gem 'rails', github: 'rails/rails', branch: 'master'
         | 
| 13 | 
            +
              gem 'activerecord', github: 'rails/rails', branch: 'master'
         | 
| 14 | 
            +
              gem 'activemodel', github: 'rails/rails', branch: 'master'
         | 
| 15 | 
            +
              gem 'arel', github: 'rails/arel', branch: 'master'
         | 
| 16 | 
            +
            end
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            [](https://travis-ci.org/state-machines/state_machines-audit_trail)
         | 
| 2 | 
            -
            [](https://codeclimate.com/github/state-machines/state_machines-audit_trail)
         | 
| 3 3 |  | 
| 4 4 | 
             
            # state_machines-audit_trail
         | 
| 5 5 | 
             
            Log transitions on a [state_machines gem](https://github.com/state-machines/state_machines) to support auditing and business process analytics.
         | 
| @@ -12,7 +12,7 @@ for any state machine. Having an audit trail gives you a complete history of the | |
| 12 12 | 
             
            to investigate incidents or perform analytics, like: _"How long does it take on average to go from state a to state b?"_,
         | 
| 13 13 | 
             
            or _"What percentage of cases goes from state a to b via state c?"_
         | 
| 14 14 |  | 
| 15 | 
            -
            For more information read [Why developers should be force-fed state machines]( | 
| 15 | 
            +
            For more information read [Why developers should be force-fed state machines](https://engineering.shopify.com/blogs/engineering/17488160-why-developers-should-be-force-fed-state-machines).
         | 
| 16 16 |  | 
| 17 17 | 
             
            ## ORM support
         | 
| 18 18 |  | 
| @@ -56,7 +56,7 @@ will generate the `SubscriptionStateTransition` model and an accompanying migrat | |
| 56 56 |  | 
| 57 57 | 
             
            ```ruby
         | 
| 58 58 | 
             
            class Subscription < ActiveRecord::Base
         | 
| 59 | 
            -
               | 
| 59 | 
            +
              state_machine :state, initial: :start do
         | 
| 60 60 | 
             
                audit_trail
         | 
| 61 61 | 
             
                ...
         | 
| 62 62 | 
             
            ```
         | 
| @@ -64,6 +64,10 @@ class Subscription < ActiveRecord::Base | |
| 64 64 | 
             
            ### That's it!
         | 
| 65 65 | 
             
            `audit_trail` will register an `after_transition` callback that is used to log all transitions including the initial state if there is one.
         | 
| 66 66 |  | 
| 67 | 
            +
            ## Upgrading from state_machine-audit_trail
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            See the wiki, https://github.com/state-machines/state_machines-audit_trail/wiki/Converting-from-former-state_machine-audit_trail-to-state_machines-audit_trail
         | 
| 70 | 
            +
             | 
| 67 71 | 
             
            ## Configuration options
         | 
| 68 72 |  | 
| 69 73 | 
             
            ### `:initial` - turn off initial state logging
         | 
| @@ -97,7 +101,7 @@ In order to utilize this feature, you need to: | |
| 97 101 | 
             
            #### Example 1 - Store a single attribute value
         | 
| 98 102 | 
             
            Store `Subscription` `field1` in `Transition` field `field1`:
         | 
| 99 103 | 
             
            ```ruby
         | 
| 100 | 
            -
            audit_trail  | 
| 104 | 
            +
            audit_trail context: :field1
         | 
| 101 105 | 
             
            ```
         | 
| 102 106 |  | 
| 103 107 | 
             
            #### Example 2 - Store multiple attribute values
         | 
| @@ -106,7 +110,25 @@ Store `Subscription` `field1` and `field2` in `Transition` fields `field1` and ` | |
| 106 110 | 
             
            audit_trail context: [:field1, :field2]
         | 
| 107 111 | 
             
            ```
         | 
| 108 112 |  | 
| 109 | 
            -
            #### Example 3 - Store  | 
| 113 | 
            +
            #### Example 3 - Store multiple values from a single context object
         | 
| 114 | 
            +
            Store `Subscription` `user` in `Transition` fields `user_id` and `user_name`:
         | 
| 115 | 
            +
            ```ruby
         | 
| 116 | 
            +
            class Subscription < ActiveRecord::Base
         | 
| 117 | 
            +
              state_machine :state, initial: :start do
         | 
| 118 | 
            +
                audit_trail context: :user
         | 
| 119 | 
            +
                ...
         | 
| 120 | 
            +
              end
         | 
| 121 | 
            +
            end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            class SubscriptionStateTransition < ActiveRecord::Base
         | 
| 124 | 
            +
              def user=(u)
         | 
| 125 | 
            +
                self.user_id = u.id
         | 
| 126 | 
            +
                self.user_name = u.name
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
            end
         | 
| 129 | 
            +
            ```
         | 
| 130 | 
            +
             | 
| 131 | 
            +
            #### Example 4 - Store simple method results
         | 
| 110 132 | 
             
            Store simple method results.
         | 
| 111 133 |  | 
| 112 134 | 
             
            Sometimes it can be useful to store dynamically computed information, such as those from a `Subscription`  method `#plan_time_remaining`
         | 
| @@ -114,7 +136,7 @@ Sometimes it can be useful to store dynamically computed information, such as th | |
| 114 136 |  | 
| 115 137 | 
             
            ```ruby
         | 
| 116 138 | 
             
            class Subscription < ActiveRecord::Base
         | 
| 117 | 
            -
               | 
| 139 | 
            +
              state_machine :state, initial: :start do
         | 
| 118 140 | 
             
                audit_trail :context: :plan_time_remaining
         | 
| 119 141 | 
             
                ...
         | 
| 120 142 |  | 
| @@ -123,12 +145,12 @@ class Subscription < ActiveRecord::Base | |
| 123 145 | 
             
                ...
         | 
| 124 146 | 
             
            ```
         | 
| 125 147 |  | 
| 126 | 
            -
            #### Example  | 
| 148 | 
            +
            #### Example 5 - Store advanced method results
         | 
| 127 149 | 
             
            Store method results that interrogate the transition for information such as `event` arguments:
         | 
| 128 150 |  | 
| 129 151 | 
             
            ```ruby
         | 
| 130 152 | 
             
            class Subscription < ActiveRecord::Base
         | 
| 131 | 
            -
               | 
| 153 | 
            +
              state_machine :state, initial: :start do
         | 
| 132 154 | 
             
                audit_trail :context: :user_name
         | 
| 133 155 | 
             
                ...
         | 
| 134 156 |  | 
    
        data/Rakefile
    CHANGED
    
    | @@ -6,4 +6,10 @@ RSpec::Core::RakeTask.new(:spec) do |task| | |
| 6 6 | 
             
              task.rspec_opts = ['--color']
         | 
| 7 7 | 
             
            end
         | 
| 8 8 |  | 
| 9 | 
            -
             | 
| 9 | 
            +
            if ENV['APPRAISAL_INITIALIZED'] || ENV['TRAVIS']
         | 
| 10 | 
            +
              task :default => :spec
         | 
| 11 | 
            +
            else
         | 
| 12 | 
            +
              require 'appraisal'
         | 
| 13 | 
            +
              Appraisal::Task.new
         | 
| 14 | 
            +
              task :default => :appraisal
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,10 @@ | |
| 1 | 
            +
            # This file was generated by Appraisal
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            source "https://rubygems.org"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            gem "rails", github: "rails/rails", branch: "master"
         | 
| 6 | 
            +
            gem "activerecord", github: "rails/rails", branch: "master"
         | 
| 7 | 
            +
            gem "activemodel", github: "rails/rails", branch: "master"
         | 
| 8 | 
            +
            gem "arel", github: "rails/arel", branch: "master"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            gemspec path: "../"
         | 
| @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            class StateMachines::AuditTrail::Backend < Struct.new(:transition_class, :owner_class, : | 
| 1 | 
            +
            class StateMachines::AuditTrail::Backend < Struct.new(:transition_class, :owner_class, :options)
         | 
| 2 2 |  | 
| 3 3 | 
             
              autoload :Mongoid, 'state_machines/audit_trail/backend/mongoid'
         | 
| 4 4 | 
             
              autoload :ActiveRecord, 'state_machines/audit_trail/backend/active_record'
         | 
| @@ -9,10 +9,18 @@ class StateMachines::AuditTrail::Backend < Struct.new(:transition_class, :owner_ | |
| 9 9 | 
             
              #   - transition: state machine transition object that state machine passes to after/before transition callbacks
         | 
| 10 10 | 
             
              #
         | 
| 11 11 | 
             
              def log(object, transition)
         | 
| 12 | 
            -
             | 
| 13 | 
            -
                 | 
| 12 | 
            +
             | 
| 13 | 
            +
                if transition.machine.presence
         | 
| 14 | 
            +
                  # full transition object
         | 
| 15 | 
            +
                  namespace = transition.machine.namespace
         | 
| 16 | 
            +
                else
         | 
| 17 | 
            +
                  # initial state open struct
         | 
| 18 | 
            +
                  namespace = transition.namespace
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
                fields = {namespace: namespace, event: transition.event ? transition.event.to_s : nil, from: transition.from, to: transition.to}
         | 
| 21 | 
            +
                [*options[:context]].each { |field|
         | 
| 14 22 | 
             
                  fields[field] = resolve_context(object, field, transition)
         | 
| 15 | 
            -
                } | 
| 23 | 
            +
                }
         | 
| 16 24 |  | 
| 17 25 | 
             
                # begin
         | 
| 18 26 | 
             
                persist(object, fields)
         | 
| @@ -30,16 +38,21 @@ class StateMachines::AuditTrail::Backend < Struct.new(:transition_class, :owner_ | |
| 30 38 | 
             
              # To add a new ORM, implement something similar to lib/state_machines/audit_trail/backend/active_record.rb
         | 
| 31 39 | 
             
              # and return from here the appropriate object based on which ORM the transition_class is using
         | 
| 32 40 | 
             
              #
         | 
| 33 | 
            -
              def self.create_for(transition_class, owner_class,  | 
| 41 | 
            +
              def self.create_for(transition_class, owner_class, options = {})
         | 
| 34 42 | 
             
                if Object.const_defined?('ActiveRecord') && transition_class.ancestors.include?(::ActiveRecord::Base)
         | 
| 35 | 
            -
                  return StateMachines::AuditTrail::Backend::ActiveRecord.new(transition_class, owner_class,  | 
| 43 | 
            +
                  return StateMachines::AuditTrail::Backend::ActiveRecord.new(transition_class, owner_class, options)
         | 
| 36 44 | 
             
                elsif Object.const_defined?('Mongoid') && transition_class.ancestors.include?(::Mongoid::Document)
         | 
| 37 | 
            -
                  return StateMachines::AuditTrail::Backend::Mongoid.new(transition_class, owner_class,  | 
| 45 | 
            +
                  return StateMachines::AuditTrail::Backend::Mongoid.new(transition_class, owner_class, options)
         | 
| 38 46 | 
             
                else
         | 
| 39 47 | 
             
                  raise 'Not implemented. Only support for ActiveRecord and Mongoid is implemented. Pull requests welcome.'
         | 
| 40 48 | 
             
                end
         | 
| 41 49 | 
             
              end
         | 
| 42 50 |  | 
| 51 | 
            +
              # Exists in case ORM layer has a different way of answering this question, but works for most.
         | 
| 52 | 
            +
              def new_record?(object)
         | 
| 53 | 
            +
                object.new_record?
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 43 56 | 
             
              protected
         | 
| 44 57 |  | 
| 45 58 | 
             
              def persist(object, fields)
         | 
| @@ -47,7 +60,15 @@ class StateMachines::AuditTrail::Backend < Struct.new(:transition_class, :owner_ | |
| 47 60 | 
             
              end
         | 
| 48 61 |  | 
| 49 62 | 
             
              def resolve_context(object, context, transition)
         | 
| 50 | 
            -
                 | 
| 63 | 
            +
                # ---------------
         | 
| 64 | 
            +
                # TODO: remove this check after we set a minimum version of Rails/ActiveRecord to 5.1+. At that time, the argument will be removed and the arity check will be enough. - rosskevin
         | 
| 65 | 
            +
                # Don't send params to Rails 5+ associations because it triggers a ton of deprecation messages.
         | 
| 66 | 
            +
                # @see https://github.com/state-machines/state_machines-audit_trail/issues/6
         | 
| 67 | 
            +
                #  check if activerecord && the context is an association
         | 
| 68 | 
            +
                skip_args = object.is_a?(::ActiveRecord::Base) && object.class.reflections.keys.include?(context.to_s)
         | 
| 69 | 
            +
                # ---------------
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                if object.method(context).arity != 0 && !skip_args
         | 
| 51 72 | 
             
                  object.send(context, transition)
         | 
| 52 73 | 
             
                else
         | 
| 53 74 | 
             
                  object.send(context)
         | 
| @@ -1,13 +1,11 @@ | |
| 1 1 | 
             
            require 'state_machines-activerecord'
         | 
| 2 2 |  | 
| 3 3 | 
             
            class StateMachines::AuditTrail::Backend::ActiveRecord < StateMachines::AuditTrail::Backend
         | 
| 4 | 
            -
               | 
| 5 | 
            -
             | 
| 6 | 
            -
              def initialize(transition_class, owner_class, context = nil)
         | 
| 4 | 
            +
              def initialize(transition_class, owner_class, options = {})
         | 
| 5 | 
            +
                super
         | 
| 7 6 | 
             
                @association = transition_class.to_s.tableize.split('/').last.to_sym
         | 
| 8 | 
            -
                 | 
| 9 | 
            -
                 | 
| 10 | 
            -
                owner_class.has_many(@association, class_name: transition_class.to_s) unless owner_class.reflect_on_association(@association)
         | 
| 7 | 
            +
                assoc_options = {class_name: transition_class.to_s}.merge(options.slice(:as))
         | 
| 8 | 
            +
                owner_class.has_many(@association, **assoc_options) unless owner_class.reflect_on_association(@association)
         | 
| 11 9 | 
             
              end
         | 
| 12 10 |  | 
| 13 11 | 
             
              def persist(object, fields)
         | 
| @@ -12,6 +12,7 @@ module StateMachines::AuditTrail::TransitionAuditing | |
| 12 12 | 
             
              #
         | 
| 13 13 | 
             
              # options:
         | 
| 14 14 | 
             
              #   - :class - custom state transition class
         | 
| 15 | 
            +
              #   - :owner_class - the class which is to own the persisted transition objects
         | 
| 15 16 | 
             
              #   - :context - methods to call/store in field of same name in the state transition class
         | 
| 16 17 | 
             
              #   - :initial - if false, won't log null => initial state transition upon instantiation
         | 
| 17 18 | 
             
              #
         | 
| @@ -21,18 +22,21 @@ module StateMachines::AuditTrail::TransitionAuditing | |
| 21 22 | 
             
                  raise ":class option[#{options[:class]}] must be a class (not a string)." unless options[:class].is_a? Class
         | 
| 22 23 | 
             
                end
         | 
| 23 24 | 
             
                transition_class = options[:class] || default_transition_class
         | 
| 25 | 
            +
                owner_class = options[:owner_class] || self.owner_class
         | 
| 24 26 |  | 
| 25 27 | 
             
                # backend implements #log to store transition information
         | 
| 26 | 
            -
                @backend = StateMachines::AuditTrail::Backend.create_for(transition_class,  | 
| 28 | 
            +
                @backend = StateMachines::AuditTrail::Backend.create_for(transition_class, owner_class, options.slice(:context, :as))
         | 
| 27 29 |  | 
| 28 30 | 
             
                # Initial state logging can be turned off. Very useful for a model with multiple state_machines using a single TransitionState object for logging
         | 
| 29 31 | 
             
                unless options[:initial] == false
         | 
| 30 32 | 
             
                  unless state_machine.action == nil
         | 
| 31 33 | 
             
                    # Log the initial transition from null => initial (upon object instantiation)
         | 
| 32 34 | 
             
                    state_machine.owner_class.after_initialize do |object|
         | 
| 33 | 
            -
                       | 
| 34 | 
            -
             | 
| 35 | 
            -
                         | 
| 35 | 
            +
                      if state_machine.backend.new_record? object
         | 
| 36 | 
            +
                        current_state = object.send(state_machine.attribute)
         | 
| 37 | 
            +
                        if !current_state.nil?
         | 
| 38 | 
            +
                          state_machine.backend.log(object, OpenStruct.new(namespace: state_machine.namespace, to: current_state))
         | 
| 39 | 
            +
                        end
         | 
| 36 40 | 
             
                      end
         | 
| 37 41 | 
             
                    end
         | 
| 38 42 | 
             
                  end
         | 
| @@ -12,6 +12,7 @@ class StateMachines::AuditTrailGenerator < ::Rails::Generators::Base | |
| 12 12 | 
             
              def create_model
         | 
| 13 13 | 
             
                args = [transition_class_name,
         | 
| 14 14 | 
             
                        "#{source_model.demodulize.tableize.singularize}:references",
         | 
| 15 | 
            +
                        'namespace:string',
         | 
| 15 16 | 
             
                        'event:string',
         | 
| 16 17 | 
             
                        'from:string',
         | 
| 17 18 | 
             
                        'to:string',
         | 
| @@ -6,6 +6,11 @@ ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':me | |
| 6 6 | 
             
            class ARModelStateTransition < ActiveRecord::Base
         | 
| 7 7 | 
             
              belongs_to :ar_model
         | 
| 8 8 | 
             
            end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            class ARModelWithNamespaceFooStateTransition < ActiveRecord::Base
         | 
| 11 | 
            +
              belongs_to :ar_model_with_namespace
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 9 14 | 
             
            class ARModelNoInitialStateTransition < ActiveRecord::Base
         | 
| 10 15 | 
             
              belongs_to :ar_model_no_initial
         | 
| 11 16 | 
             
            end
         | 
| @@ -32,7 +37,7 @@ end | |
| 32 37 |  | 
| 33 38 | 
             
            class ARModel < ActiveRecord::Base
         | 
| 34 39 |  | 
| 35 | 
            -
              state_machine :state, initial: :waiting do | 
| 40 | 
            +
              state_machine :state, initial: :waiting do
         | 
| 36 41 | 
             
                audit_trail
         | 
| 37 42 |  | 
| 38 43 | 
             
                event :start do
         | 
| @@ -47,7 +52,7 @@ end | |
| 47 52 |  | 
| 48 53 | 
             
            class ARModelNoInitial < ActiveRecord::Base
         | 
| 49 54 |  | 
| 50 | 
            -
              state_machine :state, initial: :waiting do | 
| 55 | 
            +
              state_machine :state, initial: :waiting do
         | 
| 51 56 | 
             
                audit_trail initial: false
         | 
| 52 57 |  | 
| 53 58 | 
             
                event :start do
         | 
| @@ -59,9 +64,25 @@ class ARModelNoInitial < ActiveRecord::Base | |
| 59 64 | 
             
                end
         | 
| 60 65 | 
             
              end
         | 
| 61 66 | 
             
            end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            class ARModelWithNamespace < ActiveRecord::Base
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              state_machine :foo_state, initial: :waiting, namespace: :foo do
         | 
| 71 | 
            +
                audit_trail
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                event :start do
         | 
| 74 | 
            +
                  transition [:waiting, :stopped] => :started
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                event :stop do
         | 
| 78 | 
            +
                  transition :started => :stopped
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
            end
         | 
| 82 | 
            +
             | 
| 62 83 | 
             
            #
         | 
| 63 84 | 
             
            class ARModelWithContext < ActiveRecord::Base
         | 
| 64 | 
            -
              state_machine :state, initial: :waiting do | 
| 85 | 
            +
              state_machine :state, initial: :waiting do
         | 
| 65 86 | 
             
                audit_trail context: :context
         | 
| 66 87 |  | 
| 67 88 | 
             
                event :start do
         | 
| @@ -79,7 +100,7 @@ class ARModelWithContext < ActiveRecord::Base | |
| 79 100 | 
             
            end
         | 
| 80 101 |  | 
| 81 102 | 
             
            class ARModelWithMultipleContext < ActiveRecord::Base
         | 
| 82 | 
            -
              state_machine :state, initial: :waiting do | 
| 103 | 
            +
              state_machine :state, initial: :waiting do
         | 
| 83 104 | 
             
                audit_trail context: [:context, :second_context, :context_with_args]
         | 
| 84 105 |  | 
| 85 106 | 
             
                event :start do
         | 
| @@ -150,14 +171,46 @@ class ARModelWithMultipleStateMachines < ActiveRecord::Base | |
| 150 171 | 
             
              end
         | 
| 151 172 | 
             
            end
         | 
| 152 173 |  | 
| 153 | 
            -
             | 
| 174 | 
            +
            class ARResourceStateTransition < ActiveRecord::Base
         | 
| 175 | 
            +
              belongs_to :resource, polymorphic: true
         | 
| 176 | 
            +
            end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
            class ARFirstModelWithPolymorphicStateTransition < ActiveRecord::Base
         | 
| 179 | 
            +
              state_machine :state, :initial => :pending do
         | 
| 180 | 
            +
                audit_trail class: ARResourceStateTransition, as: :ar_resource
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                event :start do
         | 
| 183 | 
            +
                  transition :pending => :in_progress
         | 
| 184 | 
            +
                end
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                event :finish do
         | 
| 187 | 
            +
                  transition :in_progress => :complete
         | 
| 188 | 
            +
                end
         | 
| 189 | 
            +
              end
         | 
| 190 | 
            +
            end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
            class ARSecondModelWithPolymorphicStateTransition < ActiveRecord::Base
         | 
| 193 | 
            +
              state_machine :state, :initial => :pending do
         | 
| 194 | 
            +
                audit_trail class: ARResourceStateTransition, as: :ar_resource
         | 
| 195 | 
            +
             | 
| 196 | 
            +
                event :start do
         | 
| 197 | 
            +
                  transition :pending => :in_progress
         | 
| 198 | 
            +
                end
         | 
| 199 | 
            +
             | 
| 200 | 
            +
                event :finish do
         | 
| 201 | 
            +
                  transition :in_progress => :complete
         | 
| 202 | 
            +
                end
         | 
| 203 | 
            +
              end
         | 
| 204 | 
            +
            end
         | 
| 205 | 
            +
             | 
| 206 | 
            +
            module SomeModule
         | 
| 154 207 | 
             
              class ARModelStateTransition < ActiveRecord::Base
         | 
| 155 | 
            -
                belongs_to : | 
| 208 | 
            +
                belongs_to :ar_model
         | 
| 156 209 | 
             
              end
         | 
| 157 210 |  | 
| 158 211 | 
             
              class ARModel < ActiveRecord::Base
         | 
| 159 212 |  | 
| 160 | 
            -
                state_machine :state, initial: :waiting do | 
| 213 | 
            +
                state_machine :state, initial: :waiting do
         | 
| 161 214 | 
             
                  audit_trail
         | 
| 162 215 |  | 
| 163 216 | 
             
                  event :start do
         | 
| @@ -174,9 +227,13 @@ end | |
| 174 227 | 
             
            #
         | 
| 175 228 | 
             
            # Generate tables
         | 
| 176 229 | 
             
            #
         | 
| 177 | 
            -
            def create_model_table(owner_class, multiple_state_machines = false)
         | 
| 230 | 
            +
            def create_model_table(owner_class, multiple_state_machines = false, state_column = nil)
         | 
| 178 231 | 
             
              ActiveRecord::Base.connection.create_table(owner_class.name.tableize) do |t|
         | 
| 179 | 
            -
                 | 
| 232 | 
            +
                if state_column.presence
         | 
| 233 | 
            +
                  t.string state_column
         | 
| 234 | 
            +
                else
         | 
| 235 | 
            +
                  t.string :state unless multiple_state_machines
         | 
| 236 | 
            +
                end
         | 
| 180 237 | 
             
                t.string :type
         | 
| 181 238 |  | 
| 182 239 | 
             
                if multiple_state_machines
         | 
| @@ -189,19 +246,21 @@ def create_model_table(owner_class, multiple_state_machines = false) | |
| 189 246 | 
             
              end
         | 
| 190 247 | 
             
            end
         | 
| 191 248 |  | 
| 192 | 
            -
            create_model_table(ARModel)
         | 
| 193 | 
            -
            create_model_table(ARModelNoInitial)
         | 
| 194 | 
            -
            create_model_table(ARModelWithContext)
         | 
| 195 | 
            -
            create_model_table(ARModelWithMultipleContext)
         | 
| 196 | 
            -
            create_model_table(ARModelWithMultipleStateMachines, true)
         | 
| 197 249 |  | 
| 250 | 
            +
            %w(ARModel ARModelNoInitial ARModelWithContext ARModelWithMultipleContext ARFirstModelWithPolymorphicStateTransition ARSecondModelWithPolymorphicStateTransition).each do |name|
         | 
| 251 | 
            +
              create_model_table(name.constantize)
         | 
| 252 | 
            +
            end
         | 
| 253 | 
            +
             | 
| 254 | 
            +
            create_model_table(ARModelWithNamespace, false, :foo_state)
         | 
| 255 | 
            +
            create_model_table(ARModelWithMultipleStateMachines, true)
         | 
| 198 256 |  | 
| 199 | 
            -
            def create_transition_table( | 
| 200 | 
            -
              class_name = "#{ | 
| 257 | 
            +
            def create_transition_table(owner_class_name, state, add_context: false, polymorphic: false)
         | 
| 258 | 
            +
              class_name = "#{owner_class_name}#{state.to_s.camelize}Transition"
         | 
| 201 259 | 
             
              ActiveRecord::Base.connection.create_table(class_name.tableize) do |t|
         | 
| 202 260 |  | 
| 203 | 
            -
                 | 
| 204 | 
            -
                t.integer  | 
| 261 | 
            +
                t.references "#{owner_class_name.demodulize.underscore}", index: false, polymorphic: polymorphic
         | 
| 262 | 
            +
                # t.integer owner_class_name.foreign_key
         | 
| 263 | 
            +
                t.string :namespace
         | 
| 205 264 | 
             
                t.string :event
         | 
| 206 265 | 
             
                t.string :from
         | 
| 207 266 | 
             
                t.string :to
         | 
| @@ -213,10 +272,14 @@ def create_transition_table(owner_class, state, add_context = false) | |
| 213 272 | 
             
              end
         | 
| 214 273 | 
             
            end
         | 
| 215 274 |  | 
| 216 | 
            -
             | 
| 217 | 
            -
            create_transition_table( | 
| 218 | 
            -
             | 
| 219 | 
            -
             | 
| 220 | 
            -
            create_transition_table( | 
| 221 | 
            -
            create_transition_table( | 
| 222 | 
            -
            create_transition_table( | 
| 275 | 
            +
            %w(ARModel ARModelNoInitial).each do |name|
         | 
| 276 | 
            +
              create_transition_table(name, :state)
         | 
| 277 | 
            +
            end
         | 
| 278 | 
            +
             | 
| 279 | 
            +
            create_transition_table("ARModelWithNamespace", :foo_state, add_context: false)
         | 
| 280 | 
            +
            create_transition_table("ARModelWithContext", :state, add_context: true)
         | 
| 281 | 
            +
            create_transition_table("ARModelWithMultipleContext", :state, add_context: true)
         | 
| 282 | 
            +
            create_transition_table("ARModelWithMultipleStateMachines", :first)
         | 
| 283 | 
            +
            create_transition_table("ARModelWithMultipleStateMachines", :second)
         | 
| 284 | 
            +
            create_transition_table("ARModelWithMultipleStateMachines", :third)
         | 
| 285 | 
            +
            create_transition_table("ARResource", :state, polymorphic: true)
         | 
    
        data/spec/helpers/mongoid.rb
    CHANGED
    
    | @@ -9,6 +9,7 @@ class MongoidTestModelStateTransition | |
| 9 9 | 
             
              include Mongoid::Timestamps
         | 
| 10 10 | 
             
              belongs_to :mongoid_test_model
         | 
| 11 11 |  | 
| 12 | 
            +
              field :namespace, type: String
         | 
| 12 13 | 
             
              field :event, type: String
         | 
| 13 14 | 
             
              field :from,  type: String
         | 
| 14 15 | 
             
              field :to,    type: String
         | 
| @@ -19,6 +20,7 @@ class MongoidTestModelWithMultipleStateMachinesFirstTransition | |
| 19 20 | 
             
              include Mongoid::Timestamps
         | 
| 20 21 | 
             
              belongs_to :mongoid_test_model
         | 
| 21 22 |  | 
| 23 | 
            +
              field :namespace, type: String
         | 
| 22 24 | 
             
              field :event, type: String
         | 
| 23 25 | 
             
              field :from,  type: String
         | 
| 24 26 | 
             
              field :to,    type: String
         | 
| @@ -29,6 +31,7 @@ class MongoidTestModelWithMultipleStateMachinesSecondTransition | |
| 29 31 | 
             
              include Mongoid::Timestamps
         | 
| 30 32 | 
             
              belongs_to :mongoid_test_model
         | 
| 31 33 |  | 
| 34 | 
            +
              field :namespace, type: String
         | 
| 32 35 | 
             
              field :event, type: String
         | 
| 33 36 | 
             
              field :from,  type: String
         | 
| 34 37 | 
             
              field :to,    type: String
         | 
    
        data/spec/helpers/mongoid.yml
    CHANGED
    
    
| @@ -9,20 +9,35 @@ require 'helpers/active_record' | |
| 9 9 | 
             
            describe StateMachines::AuditTrail::Backend::ActiveRecord do
         | 
| 10 10 |  | 
| 11 11 | 
             
              context ':initial option' do
         | 
| 12 | 
            -
                 | 
| 13 | 
            -
                   | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 12 | 
            +
                context 'default' do
         | 
| 13 | 
            +
                  it 'new object' do
         | 
| 14 | 
            +
                    target = ARModel.new
         | 
| 15 | 
            +
                    # initial transition is built but not saved
         | 
| 16 | 
            +
                    expect(target.new_record?).to be_truthy
         | 
| 17 | 
            +
                    expect(target.ar_model_state_transitions.count).to eq 0
         | 
| 18 | 
            +
                    target.save!
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                    # initial transition is saved and should be present
         | 
| 21 | 
            +
                    expect(target.new_record?).to be_falsey
         | 
| 22 | 
            +
                    expect(target.ar_model_state_transitions.count).to eq 1
         | 
| 23 | 
            +
                    state_transition = target.ar_model_state_transitions.first
         | 
| 24 | 
            +
                    assert_transition state_transition, nil, nil, 'waiting'
         | 
| 25 | 
            +
                  end
         | 
| 18 26 |  | 
| 19 | 
            -
                   | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 27 | 
            +
                  it 'create object' do
         | 
| 28 | 
            +
                    target = ARModel.create!
         | 
| 29 | 
            +
                    # initial transition is saved and should be present
         | 
| 30 | 
            +
                    expect(target.new_record?).to be_falsey
         | 
| 31 | 
            +
                    expect(target.ar_model_state_transitions.count).to eq 1
         | 
| 32 | 
            +
                    state_transition = target.ar_model_state_transitions.first
         | 
| 33 | 
            +
                    assert_transition state_transition, nil, nil, 'waiting'
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                    # ensure we don't have a second initial state transition logged (issue #4)
         | 
| 36 | 
            +
                    target = target.reload()
         | 
| 37 | 
            +
                    expect(target.ar_model_state_transitions.count).to eq 1
         | 
| 38 | 
            +
                    state_transition = target.ar_model_state_transitions.first
         | 
| 39 | 
            +
                    assert_transition state_transition, nil, nil, 'waiting'
         | 
| 40 | 
            +
                  end
         | 
| 26 41 | 
             
                end
         | 
| 27 42 |  | 
| 28 43 | 
             
                it 'false skips log' do
         | 
| @@ -38,6 +53,32 @@ describe StateMachines::AuditTrail::Backend::ActiveRecord do | |
| 38 53 | 
             
                end
         | 
| 39 54 | 
             
              end
         | 
| 40 55 |  | 
| 56 | 
            +
              context 'namespaced state_machine' do
         | 
| 57 | 
            +
                it 'should log namespace' do
         | 
| 58 | 
            +
                  target = ARModelWithNamespace.create!
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                  # initial transition is saved and should be present
         | 
| 61 | 
            +
                  expect(target.new_record?).to be_falsey
         | 
| 62 | 
            +
                  expect(target.ar_model_with_namespace_foo_state_transitions.count).to eq 1
         | 
| 63 | 
            +
                  state_transition = target.ar_model_with_namespace_foo_state_transitions.first
         | 
| 64 | 
            +
                  expect(state_transition.namespace).to eq 'foo'
         | 
| 65 | 
            +
                  expect(state_transition.from).to be_nil
         | 
| 66 | 
            +
                  expect(state_transition.to).to eq 'waiting'
         | 
| 67 | 
            +
                  expect(state_transition.event).to be_nil
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                it 'should not log namespace' do
         | 
| 71 | 
            +
                  target = ARModel.create!
         | 
| 72 | 
            +
                  expect(target.new_record?).to be_falsey
         | 
| 73 | 
            +
                  expect(target.ar_model_state_transitions.count).to eq 1
         | 
| 74 | 
            +
                  state_transition = target.ar_model_state_transitions.first
         | 
| 75 | 
            +
                  expect(state_transition.namespace).to be_nil
         | 
| 76 | 
            +
                  expect(state_transition.from).to be_nil
         | 
| 77 | 
            +
                  expect(state_transition.to).to eq 'waiting'
         | 
| 78 | 
            +
                  expect(state_transition.event).to be_nil
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 41 82 | 
             
              context '#create_for' do
         | 
| 42 83 | 
             
                it 'should be Backend::ActiveRecord' do
         | 
| 43 84 | 
             
                  backend = StateMachines::AuditTrail::Backend.create_for(ARModelWithContextStateTransition, ARModel)
         | 
| @@ -49,13 +90,13 @@ describe StateMachines::AuditTrail::Backend::ActiveRecord do | |
| 49 90 | 
             
                  expect(ARModel.reflect_on_association(:ar_model_state_transitions).collection?).to be_truthy
         | 
| 50 91 | 
             
                end
         | 
| 51 92 |  | 
| 52 | 
            -
                it 'should handle  | 
| 53 | 
            -
                  StateMachines::AuditTrail::Backend.create_for(ARModelWithContextStateTransition,  | 
| 54 | 
            -
                  expect( | 
| 93 | 
            +
                it 'should handle models within modules' do
         | 
| 94 | 
            +
                  StateMachines::AuditTrail::Backend.create_for(ARModelWithContextStateTransition, SomeModule::ARModel)
         | 
| 95 | 
            +
                  expect(SomeModule::ARModel.reflect_on_association(:ar_model_state_transitions).collection?).to be_truthy
         | 
| 55 96 | 
             
                end
         | 
| 56 97 |  | 
| 57 | 
            -
                it 'should handle  | 
| 58 | 
            -
                  StateMachines::AuditTrail::Backend.create_for( | 
| 98 | 
            +
                it 'should handle state transition models within modules' do
         | 
| 99 | 
            +
                  StateMachines::AuditTrail::Backend.create_for(SomeModule::ARModelStateTransition, ARModel)
         | 
| 59 100 | 
             
                  expect(ARModel.reflect_on_association(:ar_model_state_transitions).collection?).to be_truthy
         | 
| 60 101 | 
             
                end
         | 
| 61 102 | 
             
              end
         | 
| @@ -106,7 +147,7 @@ describe StateMachines::AuditTrail::Backend::ActiveRecord do | |
| 106 147 |  | 
| 107 148 | 
             
                context 'wants to log a single context' do
         | 
| 108 149 | 
             
                  before(:each) do
         | 
| 109 | 
            -
                    StateMachines::AuditTrail::Backend.create_for(ARModelWithContextStateTransition, ARModelWithContext, :context)
         | 
| 150 | 
            +
                    StateMachines::AuditTrail::Backend.create_for(ARModelWithContextStateTransition, ARModelWithContext, context: :context)
         | 
| 110 151 | 
             
                  end
         | 
| 111 152 |  | 
| 112 153 | 
             
                  let!(:target) { ARModelWithContext.create! }
         | 
| @@ -120,7 +161,7 @@ describe StateMachines::AuditTrail::Backend::ActiveRecord do | |
| 120 161 |  | 
| 121 162 | 
             
                context 'wants to log multiple context fields' do
         | 
| 122 163 | 
             
                  before(:each) do
         | 
| 123 | 
            -
                    StateMachines::AuditTrail::Backend.create_for(ARModelWithMultipleContextStateTransition, ARModelWithMultipleContext, [:context, :second_context, :context_with_args])
         | 
| 164 | 
            +
                    StateMachines::AuditTrail::Backend.create_for(ARModelWithMultipleContextStateTransition, ARModelWithMultipleContext, context: [:context, :second_context, :context_with_args])
         | 
| 124 165 | 
             
                  end
         | 
| 125 166 |  | 
| 126 167 | 
             
                  let!(:target) { ARModelWithMultipleContext.create! }
         | 
| @@ -222,4 +263,26 @@ describe StateMachines::AuditTrail::Backend::ActiveRecord do | |
| 222 263 | 
             
                  expect { m.complete! }.not_to raise_error
         | 
| 223 264 | 
             
                end
         | 
| 224 265 | 
             
              end
         | 
| 266 | 
            +
             | 
| 267 | 
            +
              context 'polymorphic' do
         | 
| 268 | 
            +
                it 'creates polymorphic state transitions' do
         | 
| 269 | 
            +
                  m1 = ARFirstModelWithPolymorphicStateTransition.create!
         | 
| 270 | 
            +
                  m2 = ARSecondModelWithPolymorphicStateTransition.create!
         | 
| 271 | 
            +
                  m2.start!
         | 
| 272 | 
            +
                  m2.finish!
         | 
| 273 | 
            +
             | 
| 274 | 
            +
                  expect(m1.ar_resource_state_transitions.count).to eq(1)
         | 
| 275 | 
            +
                  expect(m2.ar_resource_state_transitions.count).to eq(3)
         | 
| 276 | 
            +
                  expect(ARResourceStateTransition.count).to eq(4)
         | 
| 277 | 
            +
                end
         | 
| 278 | 
            +
              end
         | 
| 279 | 
            +
             | 
| 280 | 
            +
              private
         | 
| 281 | 
            +
             | 
| 282 | 
            +
              def assert_transition(state_transition, event, from, to)
         | 
| 283 | 
            +
                # expect(state_transition.namespace).to eq namespace
         | 
| 284 | 
            +
                expect(state_transition.event).to eq event
         | 
| 285 | 
            +
                expect(state_transition.from).to eq from
         | 
| 286 | 
            +
                expect(state_transition.to).to eq to
         | 
| 287 | 
            +
              end
         | 
| 225 288 | 
             
            end
         | 
| @@ -1,98 +1,98 @@ | |
| 1 | 
            -
            # reset integrations so that something like ActiveRecord is not loaded and conflicting
         | 
| 2 | 
            -
            require 'state_machines'
         | 
| 3 | 
            -
            StateMachines::Integrations.reset
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            require 'spec_helper'
         | 
| 6 | 
            -
            require 'state_machines-mongoid'
         | 
| 7 | 
            -
            require 'helpers/mongoid'
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            describe StateMachines::AuditTrail::Backend::Mongoid do
         | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
             | 
| 17 | 
            -
             | 
| 18 | 
            -
             | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
             | 
| 63 | 
            -
             | 
| 64 | 
            -
             | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
             | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 77 | 
            -
             | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
             | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
             | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 91 | 
            -
             | 
| 92 | 
            -
             | 
| 93 | 
            -
             | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 96 | 
            -
             | 
| 97 | 
            -
             | 
| 98 | 
            -
            end
         | 
| 1 | 
            +
            # # reset integrations so that something like ActiveRecord is not loaded and conflicting
         | 
| 2 | 
            +
            # require 'state_machines'
         | 
| 3 | 
            +
            # StateMachines::Integrations.reset
         | 
| 4 | 
            +
            #
         | 
| 5 | 
            +
            # require 'spec_helper'
         | 
| 6 | 
            +
            # require 'state_machines-mongoid'
         | 
| 7 | 
            +
            # require 'helpers/mongoid'
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            # describe StateMachines::AuditTrail::Backend::Mongoid do
         | 
| 10 | 
            +
            #
         | 
| 11 | 
            +
            #   context '#create_for' do
         | 
| 12 | 
            +
            #     it 'should create a Mongoid backend' do
         | 
| 13 | 
            +
            #       backend = StateMachines::AuditTrail::Backend.create_for(MongoidTestModelStateTransition, MongoidTestModel)
         | 
| 14 | 
            +
            #       expect(backend).to be_instance_of(StateMachines::AuditTrail::Backend::Mongoid)
         | 
| 15 | 
            +
            #     end
         | 
| 16 | 
            +
            #   end
         | 
| 17 | 
            +
            #
         | 
| 18 | 
            +
            #   context 'single state machine' do
         | 
| 19 | 
            +
            #     let!(:target) { MongoidTestModel.create! }
         | 
| 20 | 
            +
            #
         | 
| 21 | 
            +
            #     it 'should populate all fields' do
         | 
| 22 | 
            +
            #       target.start!
         | 
| 23 | 
            +
            #       last_transition = MongoidTestModelStateTransition.where(:mongoid_test_model_id => target.id).last
         | 
| 24 | 
            +
            #
         | 
| 25 | 
            +
            #       expect(last_transition.event).to eq 'start'
         | 
| 26 | 
            +
            #       expect(last_transition.from).to eq 'waiting'
         | 
| 27 | 
            +
            #       expect(last_transition.to).to eq 'started'
         | 
| 28 | 
            +
            #       expect(last_transition.created_at).to be_within(10.seconds).of(DateTime.now)
         | 
| 29 | 
            +
            #     end
         | 
| 30 | 
            +
            #
         | 
| 31 | 
            +
            #     it 'should log multiple events' do
         | 
| 32 | 
            +
            #       expect { target.start && target.stop && target.start }.to change(MongoidTestModelStateTransition, :count).by(3)
         | 
| 33 | 
            +
            #     end
         | 
| 34 | 
            +
            #
         | 
| 35 | 
            +
            #     it 'do nothing on failed transition' do
         | 
| 36 | 
            +
            #       expect { target.stop }.not_to change(MongoidTestModelStateTransition, :count)
         | 
| 37 | 
            +
            #     end
         | 
| 38 | 
            +
            #   end
         | 
| 39 | 
            +
            #
         | 
| 40 | 
            +
            #   context 'multiple state machines' do
         | 
| 41 | 
            +
            #     let!(:target) { MongoidTestModelWithMultipleStateMachines.create! }
         | 
| 42 | 
            +
            #
         | 
| 43 | 
            +
            #     it 'should log a state transition for the affected state machine' do
         | 
| 44 | 
            +
            #       expect { target.begin_first! }.to change(MongoidTestModelWithMultipleStateMachinesFirstTransition, :count).by(1)
         | 
| 45 | 
            +
            #     end
         | 
| 46 | 
            +
            #
         | 
| 47 | 
            +
            #     it 'should not log a state transition for the unaffected state machine' do
         | 
| 48 | 
            +
            #       expect { target.begin_first! }.not_to change(MongoidTestModelWithMultipleStateMachinesSecondTransition, :count)
         | 
| 49 | 
            +
            #     end
         | 
| 50 | 
            +
            #   end
         | 
| 51 | 
            +
            #
         | 
| 52 | 
            +
            #   context 'on an object with a state machine having an initial state' do
         | 
| 53 | 
            +
            #     let(:target_class) { MongoidTestModelWithMultipleStateMachines }
         | 
| 54 | 
            +
            #     let(:state_transition_class) { MongoidTestModelWithMultipleStateMachinesFirstTransition }
         | 
| 55 | 
            +
            #
         | 
| 56 | 
            +
            #     it 'should log a state transition for the inital state' do
         | 
| 57 | 
            +
            #       expect { target_class.create! }.to change(state_transition_class, :count).by(1)
         | 
| 58 | 
            +
            #     end
         | 
| 59 | 
            +
            #
         | 
| 60 | 
            +
            #     it 'should only set the :to state for the initial transition' do
         | 
| 61 | 
            +
            #       target_class.create!
         | 
| 62 | 
            +
            #       initial_transition = state_transition_class.last
         | 
| 63 | 
            +
            #       expect(initial_transition.event).to be_nil
         | 
| 64 | 
            +
            #       expect(initial_transition.from).to be_nil
         | 
| 65 | 
            +
            #       expect(initial_transition.to).to eq 'beginning'
         | 
| 66 | 
            +
            #       expect(initial_transition.created_at).to be_within(10.seconds).of(DateTime.now)
         | 
| 67 | 
            +
            #     end
         | 
| 68 | 
            +
            #   end
         | 
| 69 | 
            +
            #
         | 
| 70 | 
            +
            #   context 'on an object with a state machine not having an initial state' do
         | 
| 71 | 
            +
            #     let(:target_class) { MongoidTestModelWithMultipleStateMachines }
         | 
| 72 | 
            +
            #     let(:state_transition_class) { MongoidTestModelWithMultipleStateMachinesSecondTransition }
         | 
| 73 | 
            +
            #
         | 
| 74 | 
            +
            #     it 'should not log a transition when the object is created' do
         | 
| 75 | 
            +
            #       expect { target_class.create! }.not_to change(state_transition_class, :count)
         | 
| 76 | 
            +
            #     end
         | 
| 77 | 
            +
            #
         | 
| 78 | 
            +
            #     it 'should log a transition for the first event' do
         | 
| 79 | 
            +
            #       expect { target_class.create.begin_second! }.to change(state_transition_class, :count).by(1)
         | 
| 80 | 
            +
            #     end
         | 
| 81 | 
            +
            #
         | 
| 82 | 
            +
            #     it 'should not set a value for the :from state on the first transition' do
         | 
| 83 | 
            +
            #       target_class.create.begin_second!
         | 
| 84 | 
            +
            #       first_transition = state_transition_class.last
         | 
| 85 | 
            +
            #       expect(first_transition.event).to eq 'begin_second'
         | 
| 86 | 
            +
            #       expect(first_transition.from).to be_nil
         | 
| 87 | 
            +
            #       expect(first_transition.to).to eq 'beginning_second'
         | 
| 88 | 
            +
            #       expect(first_transition.created_at).to be_within(10.seconds).of(DateTime.now)
         | 
| 89 | 
            +
            #     end
         | 
| 90 | 
            +
            #   end
         | 
| 91 | 
            +
            #
         | 
| 92 | 
            +
            #   context 'on a class using STI' do
         | 
| 93 | 
            +
            #     it 'should properly grab the class name from STI models' do
         | 
| 94 | 
            +
            #       m = MongoidTestModelDescendant.create!
         | 
| 95 | 
            +
            #       expect { m.start! }.not_to raise_error
         | 
| 96 | 
            +
            #     end
         | 
| 97 | 
            +
            #   end
         | 
| 98 | 
            +
            # end
         | 
| @@ -10,7 +10,7 @@ | |
| 10 10 | 
             
            # describe StateMachines::AuditTrailGenerator, type: :generator do
         | 
| 11 11 | 
             
            #
         | 
| 12 12 | 
             
            #   destination File.expand_path('../../../../tmp', __FILE__)
         | 
| 13 | 
            -
            #   arguments %w( | 
| 13 | 
            +
            #   arguments %w(SomeModule::Subscription state)
         | 
| 14 14 | 
             
            #
         | 
| 15 15 | 
             
            #   before(:all) do
         | 
| 16 16 | 
             
            #     prepare_destination
         | 
| @@ -36,7 +36,7 @@ | |
| 36 36 | 
             
            #                                       end
         | 
| 37 37 | 
             
            #                                       directory 'some_namespace' do
         | 
| 38 38 | 
             
            #                                         file 'subscription_state_transition.rb' do
         | 
| 39 | 
            -
            #                                           contains 'class  | 
| 39 | 
            +
            #                                           contains 'class SomeModule::SubscriptionStateTransition'
         | 
| 40 40 | 
             
            #                                         end
         | 
| 41 41 | 
             
            #                                       end
         | 
| 42 42 | 
             
            #                                     end
         | 
| @@ -22,12 +22,17 @@ Gem::Specification.new do |s| | |
| 22 22 | 
             
              s.add_development_dependency('state_machines-mongoid')
         | 
| 23 23 | 
             
              s.add_development_dependency('rake')
         | 
| 24 24 | 
             
              s.add_development_dependency('rspec', '>= 3.0.0')
         | 
| 25 | 
            -
              s.add_development_dependency('activerecord', '>=  | 
| 26 | 
            -
               | 
| 27 | 
            -
             | 
| 28 | 
            -
               | 
| 25 | 
            +
              s.add_development_dependency('activerecord', '>= 5.0.0')
         | 
| 26 | 
            +
              if(defined?(JRUBY_VERSION))
         | 
| 27 | 
            +
                s.add_development_dependency('activerecord-jdbcsqlite3-adapter')
         | 
| 28 | 
            +
              else
         | 
| 29 | 
            +
                s.add_development_dependency('sqlite3')
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
              s.add_development_dependency('mongoid', '>= 6.0.0.beta')
         | 
| 32 | 
            +
              s.add_development_dependency('bson')
         | 
| 29 33 | 
             
              s.add_development_dependency('generator_spec')
         | 
| 30 | 
            -
              s.add_development_dependency('rails', '>=  | 
| 34 | 
            +
              s.add_development_dependency('rails', '>= 5.0.0')
         | 
| 35 | 
            +
              s.add_development_dependency('appraisal', '~> 2.2.0')
         | 
| 31 36 |  | 
| 32 37 | 
             
              s.files = `git ls-files`.split($/).reject { |f| f =~ /^samples\// }
         | 
| 33 38 | 
             
              s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: state_machines-audit_trail
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version:  | 
| 4 | 
            +
              version: 2.0.2
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Kevin Ross
         | 
| @@ -10,7 +10,7 @@ authors: | |
| 10 10 | 
             
            autorequire: 
         | 
| 11 11 | 
             
            bindir: bin
         | 
| 12 12 | 
             
            cert_chain: []
         | 
| 13 | 
            -
            date:  | 
| 13 | 
            +
            date: 2020-06-09 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: state_machines
         | 
| @@ -88,14 +88,14 @@ dependencies: | |
| 88 88 | 
             
                requirements:
         | 
| 89 89 | 
             
                - - ">="
         | 
| 90 90 | 
             
                  - !ruby/object:Gem::Version
         | 
| 91 | 
            -
                    version:  | 
| 91 | 
            +
                    version: 5.0.0
         | 
| 92 92 | 
             
              type: :development
         | 
| 93 93 | 
             
              prerelease: false
         | 
| 94 94 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 95 95 | 
             
                requirements:
         | 
| 96 96 | 
             
                - - ">="
         | 
| 97 97 | 
             
                  - !ruby/object:Gem::Version
         | 
| 98 | 
            -
                    version:  | 
| 98 | 
            +
                    version: 5.0.0
         | 
| 99 99 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 100 100 | 
             
              name: sqlite3
         | 
| 101 101 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -116,16 +116,16 @@ dependencies: | |
| 116 116 | 
             
                requirements:
         | 
| 117 117 | 
             
                - - ">="
         | 
| 118 118 | 
             
                  - !ruby/object:Gem::Version
         | 
| 119 | 
            -
                    version:  | 
| 119 | 
            +
                    version: 6.0.0.beta
         | 
| 120 120 | 
             
              type: :development
         | 
| 121 121 | 
             
              prerelease: false
         | 
| 122 122 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 123 123 | 
             
                requirements:
         | 
| 124 124 | 
             
                - - ">="
         | 
| 125 125 | 
             
                  - !ruby/object:Gem::Version
         | 
| 126 | 
            -
                    version:  | 
| 126 | 
            +
                    version: 6.0.0.beta
         | 
| 127 127 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 128 | 
            -
              name:  | 
| 128 | 
            +
              name: bson
         | 
| 129 129 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 130 130 | 
             
                requirements:
         | 
| 131 131 | 
             
                - - ">="
         | 
| @@ -158,14 +158,28 @@ dependencies: | |
| 158 158 | 
             
                requirements:
         | 
| 159 159 | 
             
                - - ">="
         | 
| 160 160 | 
             
                  - !ruby/object:Gem::Version
         | 
| 161 | 
            -
                    version:  | 
| 161 | 
            +
                    version: 5.0.0
         | 
| 162 162 | 
             
              type: :development
         | 
| 163 163 | 
             
              prerelease: false
         | 
| 164 164 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 165 165 | 
             
                requirements:
         | 
| 166 166 | 
             
                - - ">="
         | 
| 167 167 | 
             
                  - !ruby/object:Gem::Version
         | 
| 168 | 
            -
                    version:  | 
| 168 | 
            +
                    version: 5.0.0
         | 
| 169 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 170 | 
            +
              name: appraisal
         | 
| 171 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 172 | 
            +
                requirements:
         | 
| 173 | 
            +
                - - "~>"
         | 
| 174 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 175 | 
            +
                    version: 2.2.0
         | 
| 176 | 
            +
              type: :development
         | 
| 177 | 
            +
              prerelease: false
         | 
| 178 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 179 | 
            +
                requirements:
         | 
| 180 | 
            +
                - - "~>"
         | 
| 181 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 182 | 
            +
                    version: 2.2.0
         | 
| 169 183 | 
             
            description: Log transitions on a state_machines to support auditing and business
         | 
| 170 184 | 
             
              process analytics.
         | 
| 171 185 | 
             
            email:
         | 
| @@ -178,11 +192,19 @@ extra_rdoc_files: [] | |
| 178 192 | 
             
            files:
         | 
| 179 193 | 
             
            - ".gitignore"
         | 
| 180 194 | 
             
            - ".rspec"
         | 
| 195 | 
            +
            - ".ruby-gemset"
         | 
| 196 | 
            +
            - ".ruby-version"
         | 
| 181 197 | 
             
            - ".travis.yml"
         | 
| 198 | 
            +
            - Appraisals
         | 
| 182 199 | 
             
            - Gemfile
         | 
| 183 200 | 
             
            - LICENSE
         | 
| 184 201 | 
             
            - README.md
         | 
| 185 202 | 
             
            - Rakefile
         | 
| 203 | 
            +
            - gemfiles/rails_5.0.gemfile
         | 
| 204 | 
            +
            - gemfiles/rails_5.1.gemfile
         | 
| 205 | 
            +
            - gemfiles/rails_5.2.gemfile
         | 
| 206 | 
            +
            - gemfiles/rails_6.0.gemfile
         | 
| 207 | 
            +
            - gemfiles/rails_edge.gemfile
         | 
| 186 208 | 
             
            - lib/state_machines-audit_trail.rb
         | 
| 187 209 | 
             
            - lib/state_machines/audit_trail.rb
         | 
| 188 210 | 
             
            - lib/state_machines/audit_trail/backend.rb
         | 
| @@ -220,8 +242,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 220 242 | 
             
                - !ruby/object:Gem::Version
         | 
| 221 243 | 
             
                  version: '0'
         | 
| 222 244 | 
             
            requirements: []
         | 
| 223 | 
            -
             | 
| 224 | 
            -
            rubygems_version: 2.4.5
         | 
| 245 | 
            +
            rubygems_version: 3.0.3
         | 
| 225 246 | 
             
            signing_key: 
         | 
| 226 247 | 
             
            specification_version: 4
         | 
| 227 248 | 
             
            summary: Log transitions on a state_machines to support auditing and business process
         |