circulator 2.1.2 → 2.1.3
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 -2
- data/README.md +33 -2
- data/lib/circulator/version.rb +1 -1
- data/lib/circulator.rb +26 -0
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: bdd2e4e17046d72b53d25ea469b8f037316abf74cb7a34fe010091ff4f8b5bfa
         | 
| 4 | 
            +
              data.tar.gz: 879a93ab33bb08c07fb6239ce490c5d900272cbd3cd03a65c66516f95439499e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 910cd9755d9b9c02996d9d38329082733d019019151c19bc839663893e3523a6c64be9149485317bc7a0979f10223d15c4e0bb34ae0a9942f30d1c473acf8378
         | 
| 7 | 
            +
              data.tar.gz: a98cad092d4da49cf93c38db6462489730061c38439f9825e2d2378ef58def38d3db243784c570f50697704442d271d8ac3aa0b1eddd5147e7f4a65b2a346c8a
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -5,8 +5,12 @@ All notable changes to this project will be documented in this file. | |
| 5 5 | 
             
            The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
         | 
| 6 6 | 
             
            and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
         | 
| 7 7 |  | 
| 8 | 
            -
            ## [2.1. | 
| 8 | 
            +
            ## [2.1.3] - 2025-10-27
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            ### Fixed
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            - Ignore nil states in predicate methods (73c74c2)
         | 
| 9 13 |  | 
| 10 14 | 
             
            ### Added
         | 
| 11 15 |  | 
| 12 | 
            -
            -  | 
| 16 | 
            +
            - Attribute predicate methods and documentation (8f9cc33)
         | 
    
        data/README.md
    CHANGED
    
    | @@ -6,7 +6,7 @@ A lightweight and flexible state machine implementation for Ruby that allows you | |
| 6 6 |  | 
| 7 7 | 
             
            - **Lightweight**: Minimal dependencies and simple implementation
         | 
| 8 8 | 
             
            - **Flexible DSL**: Intuitive syntax for defining states and transitions
         | 
| 9 | 
            -
            - **Dynamic Method Generation**: Automatically creates  | 
| 9 | 
            +
            - **Dynamic Method Generation**: Automatically creates action methods for transitions and predicate methods for state checks
         | 
| 10 10 | 
             
            - **Conditional Transitions**: Support for guards and conditional logic
         | 
| 11 11 | 
             
            - **Nested State Dependencies**: State machines can depend on the state of other attributes
         | 
| 12 12 | 
             
            - **Transition Callbacks**: Execute code before, during, or after transitions
         | 
| @@ -72,6 +72,37 @@ order.status_ship     # => :shipped | |
| 72 72 | 
             
            order.status_deliver  # => :delivered
         | 
| 73 73 | 
             
            ```
         | 
| 74 74 |  | 
| 75 | 
            +
            ### Generated Methods
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            Circulator automatically generates two types of helper methods for your state machines:
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            #### Action Methods
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            For each action defined in your state machine, Circulator creates a method that performs the transition:
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            ```ruby
         | 
| 84 | 
            +
            order.status_process  # Transitions from :pending to :processing
         | 
| 85 | 
            +
            order.status_cancel   # Transitions to :cancelled
         | 
| 86 | 
            +
            ```
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            #### State Predicate Methods
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            For each state in your state machine, Circulator creates a predicate method to check the current state:
         | 
| 91 | 
            +
             | 
| 92 | 
            +
            ```ruby
         | 
| 93 | 
            +
            order.status = :pending
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            order.status_pending?     # => true
         | 
| 96 | 
            +
            order.status_processing?  # => false
         | 
| 97 | 
            +
            order.status_shipped?     # => false
         | 
| 98 | 
            +
             | 
| 99 | 
            +
            order.status_process
         | 
| 100 | 
            +
            order.status_processing?  # => true
         | 
| 101 | 
            +
            order.status_pending?     # => false
         | 
| 102 | 
            +
            ```
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            These predicate methods work with both symbol and string values, automatically converting strings to symbols for comparison.
         | 
| 105 | 
            +
             | 
| 75 106 | 
             
            ### Advanced Features
         | 
| 76 107 |  | 
| 77 108 | 
             
            #### Conditional Transitions with Guards
         | 
| @@ -227,7 +258,7 @@ Circulator distinguishes itself from other Ruby state machine libraries through | |
| 227 258 | 
             
            - **Minimal Magic**: Unlike AASM and state_machines, Circulator uses straightforward Ruby metaprogramming without complex DSL magic
         | 
| 228 259 | 
             
            - **No Dependencies**: Works with plain Ruby objects without requiring Rails, ActiveRecord, or other frameworks
         | 
| 229 260 | 
             
            - **Lightweight**: Smaller footprint compared to feature-heavy alternatives
         | 
| 230 | 
            -
            - **Clear Method Names**: Generated methods follow predictable naming patterns (`status_approve`, ` | 
| 261 | 
            +
            - **Clear Method Names**: Generated methods follow predictable naming patterns (`status_approve`, `status_pending?`)
         | 
| 231 262 | 
             
            - **Flexible Architecture**: Easy to extend and customize for specific needs
         | 
| 232 263 |  | 
| 233 264 | 
             
            ### When to Use Circulator
         | 
    
        data/lib/circulator/version.rb
    CHANGED
    
    
    
        data/lib/circulator.rb
    CHANGED
    
    | @@ -145,12 +145,38 @@ module Circulator | |
| 145 145 | 
             
                  Circulator.methodize_name(model)
         | 
| 146 146 | 
             
                end
         | 
| 147 147 |  | 
| 148 | 
            +
                states = Set.new
         | 
| 148 149 | 
             
                @flows.dig(model_key, attribute_name).transition_map.each do |action, transitions|
         | 
| 150 | 
            +
                  transitions.each do |from_state, transition_data|
         | 
| 151 | 
            +
                    states.add(from_state)
         | 
| 152 | 
            +
                    # Add the 'to' state if it's not a callable
         | 
| 153 | 
            +
                    unless transition_data[:to].respond_to?(:call)
         | 
| 154 | 
            +
                      states.add(transition_data[:to])
         | 
| 155 | 
            +
                    end
         | 
| 156 | 
            +
                  end
         | 
| 149 157 | 
             
                  define_flow_method(attribute_name:, action:, transitions:, object:, owner: flow_module)
         | 
| 150 158 | 
             
                end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                # Define predicate methods for each state (skip nil)
         | 
| 161 | 
            +
                states.each do |state|
         | 
| 162 | 
            +
                  next if state.nil?
         | 
| 163 | 
            +
                  define_state_method(attribute_name:, state:, object:, owner: flow_module)
         | 
| 164 | 
            +
                end
         | 
| 151 165 | 
             
              end
         | 
| 152 166 | 
             
              alias_method :circulator, :flow
         | 
| 153 167 |  | 
| 168 | 
            +
              def define_state_method(attribute_name:, state:, object:, owner:)
         | 
| 169 | 
            +
                object_attribute_method = [object, attribute_name, state].compact.join("_") << "?"
         | 
| 170 | 
            +
                return if owner.method_defined?(object_attribute_method)
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                owner.define_method(object_attribute_method) do
         | 
| 173 | 
            +
                  current_value = send(attribute_name)
         | 
| 174 | 
            +
                  # Convert to symbol for comparison if possible
         | 
| 175 | 
            +
                  current_value = current_value.to_sym if current_value.respond_to?(:to_sym)
         | 
| 176 | 
            +
                  current_value == state
         | 
| 177 | 
            +
                end
         | 
| 178 | 
            +
              end
         | 
| 179 | 
            +
             | 
| 154 180 | 
             
              def define_flow_method(attribute_name:, action:, transitions:, object:, owner:)
         | 
| 155 181 | 
             
                object_attribute_method = [object, attribute_name, action].compact.join("_")
         | 
| 156 182 | 
             
                raise ArgumentError, "Method already defined: #{object_attribute_method}" if owner.method_defined?(object_attribute_method)
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: circulator
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 2.1. | 
| 4 | 
            +
              version: 2.1.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Jim Gay
         | 
| @@ -46,7 +46,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 46 46 | 
             
                - !ruby/object:Gem::Version
         | 
| 47 47 | 
             
                  version: '0'
         | 
| 48 48 | 
             
            requirements: []
         | 
| 49 | 
            -
            rubygems_version: 3. | 
| 49 | 
            +
            rubygems_version: 3.7.2
         | 
| 50 50 | 
             
            specification_version: 4
         | 
| 51 51 | 
             
            summary: Simple state machine
         | 
| 52 52 | 
             
            test_files: []
         |