inoculate 0.2.0 → 0.4.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 +9 -0
- data/README.md +102 -1
- data/lib/inoculate/configurer.rb +21 -2
- data/lib/inoculate/manufacturer.rb +103 -25
- data/lib/inoculate/version.rb +1 -1
- data/sig/inoculate.rbs +8 -4
- 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: 7bd8610b9bbde1304734505a64fdf22c8665961e3b02d93171ac4fc6ccf313aa
         | 
| 4 | 
            +
              data.tar.gz: 66ee174fa4bd02dfd671a39a946a8343da1d63bb88f9be05ee94816d033a5e4e
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: bbc2655324e68cd2ad977192b81f9cbef0d63b72da91f05521c59eb91f1d58993da68dbcd8d4f6b69be5e5d93708e847f567955f80cb042761e187b64c1bcdbc
         | 
| 7 | 
            +
              data.tar.gz: ef316f9b6e6dfa9cd42811f8af5082f402d0c03478a280a2728b61ce9c706a9e0b1cd0249921d18818cfa85b28ccf81969a1330744c3d8d19e95e5fd4f73a81c
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,12 @@ | |
| 1 | 
            +
            ## v0.4.0 \[Unreleased]
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Add singleton dependency registration.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ## v0.3.0 \[2022-10-11]
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * Add instance dependency registration.
         | 
| 8 | 
            +
            * Only allow blocks (and Procs) as dependency factories.
         | 
| 9 | 
            +
             | 
| 1 10 | 
             
            ## v0.2.0 \[2022-10-11]
         | 
| 2 11 |  | 
| 3 12 | 
             
            * Build modules at initialization time so that usage is always thread-safe.
         | 
    
        data/README.md
    CHANGED
    
    | @@ -24,6 +24,8 @@ It provides several life-cycles and provides dependency access through private a | |
| 24 24 | 
             
            2. [Usage](#usage)
         | 
| 25 25 | 
             
               1. [Dependency Life Cycles](#dependency-life-cycles)
         | 
| 26 26 | 
             
                  1. [Transient](#transient)
         | 
| 27 | 
            +
                  2. [Instance](#instance)
         | 
| 28 | 
            +
                  3. [Singleton](#singleton)
         | 
| 27 29 | 
             
               2. [Renaming the Declaration API](#renaming-the-declaration-api)
         | 
| 28 30 | 
             
               3. [Hide Your Dependency on Inoculate](#hide-your-dependency-on-inoculate)
         | 
| 29 31 | 
             
            3. [Installation](#installation)
         | 
| @@ -99,16 +101,115 @@ class Example | |
| 99 101 | 
             
               end
         | 
| 100 102 | 
             
            end
         | 
| 101 103 |  | 
| 102 | 
            -
             | 
| 104 | 
            +
            a = Example.new
         | 
| 105 | 
            +
            puts a, a, a
         | 
| 103 106 | 
             
            ```
         | 
| 104 107 |  | 
| 105 108 | 
             
            This results in:
         | 
| 106 109 |  | 
| 107 110 | 
             
            ```
         | 
| 108 111 | 
             
            Count is: 0
         | 
| 112 | 
            +
            Count is: 0
         | 
| 113 | 
            +
            Count is: 0
         | 
| 109 114 | 
             
            => nil    
         | 
| 110 115 | 
             
            ```
         | 
| 111 116 |  | 
| 117 | 
            +
            #### Instance
         | 
| 118 | 
            +
            Instance dependencies are constructed once for each instance of a dependent class.
         | 
| 119 | 
            +
             | 
| 120 | 
            +
            ```ruby
         | 
| 121 | 
            +
            class Counter
         | 
| 122 | 
            +
               attr_reader :count
         | 
| 123 | 
            +
             | 
| 124 | 
            +
               def initialize
         | 
| 125 | 
            +
                  @count = 0
         | 
| 126 | 
            +
               end
         | 
| 127 | 
            +
               
         | 
| 128 | 
            +
               def inc
         | 
| 129 | 
            +
                  @count += 1
         | 
| 130 | 
            +
               end
         | 
| 131 | 
            +
            end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            Inoculate.initialize do |config|
         | 
| 134 | 
            +
               config.instance(:counter) { Counter.new }
         | 
| 135 | 
            +
            end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
            class Example
         | 
| 138 | 
            +
               include Inoculate::Porter
         | 
| 139 | 
            +
               inoculate_with :counter
         | 
| 140 | 
            +
               
         | 
| 141 | 
            +
               def initialize(name)
         | 
| 142 | 
            +
                  @name = name
         | 
| 143 | 
            +
               end
         | 
| 144 | 
            +
               
         | 
| 145 | 
            +
               def to_s
         | 
| 146 | 
            +
                  counter.inc
         | 
| 147 | 
            +
                  "[#{@name}] Count is: #{counter.count}"
         | 
| 148 | 
            +
               end
         | 
| 149 | 
            +
            end
         | 
| 150 | 
            +
             | 
| 151 | 
            +
            a = Example.new("a")
         | 
| 152 | 
            +
            b = Example.new("b")
         | 
| 153 | 
            +
            puts a, a, b
         | 
| 154 | 
            +
            ```
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            This results in:
         | 
| 157 | 
            +
             | 
| 158 | 
            +
            ```
         | 
| 159 | 
            +
            [a] Count is: 1
         | 
| 160 | 
            +
            [a] Count is: 2
         | 
| 161 | 
            +
            [b] Count is: 1
         | 
| 162 | 
            +
            => nil  
         | 
| 163 | 
            +
            ```
         | 
| 164 | 
            +
             | 
| 165 | 
            +
            #### Singleton
         | 
| 166 | 
            +
            Singleton dependencies are constructed once.
         | 
| 167 | 
            +
             | 
| 168 | 
            +
            ```ruby
         | 
| 169 | 
            +
            class Counter
         | 
| 170 | 
            +
               attr_reader :count
         | 
| 171 | 
            +
             | 
| 172 | 
            +
               def initialize
         | 
| 173 | 
            +
                  @count = 0
         | 
| 174 | 
            +
               end
         | 
| 175 | 
            +
               
         | 
| 176 | 
            +
               def inc
         | 
| 177 | 
            +
                  @count += 1
         | 
| 178 | 
            +
               end
         | 
| 179 | 
            +
            end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
            Inoculate.initialize do |config|
         | 
| 182 | 
            +
               config.singleton(:counter) { Counter.new }
         | 
| 183 | 
            +
            end
         | 
| 184 | 
            +
             | 
| 185 | 
            +
            class Example
         | 
| 186 | 
            +
               include Inoculate::Porter
         | 
| 187 | 
            +
               inoculate_with :counter
         | 
| 188 | 
            +
               
         | 
| 189 | 
            +
               def initialize(name)
         | 
| 190 | 
            +
                  @name = name
         | 
| 191 | 
            +
               end
         | 
| 192 | 
            +
               
         | 
| 193 | 
            +
               def to_s
         | 
| 194 | 
            +
                  counter.inc
         | 
| 195 | 
            +
                  "[#{@name}] Count is: #{counter.count}"
         | 
| 196 | 
            +
               end
         | 
| 197 | 
            +
            end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
            a = Example.new("a")
         | 
| 200 | 
            +
            b = Example.new("b")
         | 
| 201 | 
            +
            puts a, a, b
         | 
| 202 | 
            +
            ```
         | 
| 203 | 
            +
             | 
| 204 | 
            +
            This results in:
         | 
| 205 | 
            +
             | 
| 206 | 
            +
            ```
         | 
| 207 | 
            +
            [a] Count is: 1
         | 
| 208 | 
            +
            [a] Count is: 2                         
         | 
| 209 | 
            +
            [b] Count is: 3                         
         | 
| 210 | 
            +
            => nil   
         | 
| 211 | 
            +
            ```
         | 
| 212 | 
            +
             | 
| 112 213 | 
             
            ### Renaming the Declaration API
         | 
| 113 214 | 
             
            The `inoculate_with` API is named to avoid immediate collisions with other modules
         | 
| 114 215 | 
             
            and code you may have. You can use it as-is, or rename it to something you see fit
         | 
    
        data/lib/inoculate/configurer.rb
    CHANGED
    
    | @@ -13,8 +13,27 @@ module Inoculate | |
| 13 13 | 
             
                # @see Manufacturer#transient
         | 
| 14 14 | 
             
                #
         | 
| 15 15 | 
             
                # @since 0.1.0
         | 
| 16 | 
            -
                def transient(name,  | 
| 17 | 
            -
                  manufacturer.transient(name,  | 
| 16 | 
            +
                def transient(name, &block)
         | 
| 17 | 
            +
                  manufacturer.transient(name, &block)
         | 
| 18 | 
            +
                  nil
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                # Register an instance dependency.
         | 
| 22 | 
            +
                # @see Manufacturer#instance
         | 
| 23 | 
            +
                #
         | 
| 24 | 
            +
                # @since 0.3.0
         | 
| 25 | 
            +
                def instance(name, &block)
         | 
| 26 | 
            +
                  manufacturer.instance(name, &block)
         | 
| 27 | 
            +
                  nil
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                # Register a singleton dependency.
         | 
| 31 | 
            +
                # @see Manufacturer#singleton
         | 
| 32 | 
            +
                #
         | 
| 33 | 
            +
                # @since 0.4.0
         | 
| 34 | 
            +
                def singleton(name, &block)
         | 
| 35 | 
            +
                  manufacturer.singleton(name, &block)
         | 
| 36 | 
            +
                  nil
         | 
| 18 37 | 
             
                end
         | 
| 19 38 |  | 
| 20 39 | 
             
                private
         | 
| @@ -5,7 +5,6 @@ require "digest" | |
| 5 5 | 
             
            module Inoculate
         | 
| 6 6 | 
             
              # Registers and builds dependency injection modules.
         | 
| 7 7 | 
             
              # @todo singleton life cycle
         | 
| 8 | 
            -
              # @todo instance life cycle
         | 
| 9 8 | 
             
              # @todo thread singleton life cycle
         | 
| 10 9 | 
             
              #
         | 
| 11 10 | 
             
              # @since 0.1.0
         | 
| @@ -28,49 +27,124 @@ module Inoculate | |
| 28 27 | 
             
                #   manufacturer.transient(:sha1_hasher) { Digest::SHA1.new }
         | 
| 29 28 | 
             
                #
         | 
| 30 29 | 
             
                # @example With a Proc
         | 
| 31 | 
            -
                #   manufacturer.transient(:sha1_hasher,  | 
| 32 | 
            -
                #
         | 
| 33 | 
            -
                # @example With anything Callable
         | 
| 34 | 
            -
                #   class HashingBuilder
         | 
| 35 | 
            -
                #     def call = Digest::SHA1.new
         | 
| 36 | 
            -
                #   end
         | 
| 37 | 
            -
                #   manufacturer.transient(:sha1_hasher, HashingBuilder.new)
         | 
| 30 | 
            +
                #   manufacturer.transient(:sha1_hasher, &-> { Digest::SHA1.new })
         | 
| 38 31 | 
             
                #
         | 
| 39 32 | 
             
                # @param name [Symbol, #to_sym] the dependency name which will be used to access it
         | 
| 40 | 
            -
                # @param  | 
| 41 | 
            -
                # @param block [Proc, nil] an alternative builder callable
         | 
| 33 | 
            +
                # @param block [Block, Proc] a factory method to build the dependency
         | 
| 42 34 | 
             
                #
         | 
| 43 | 
            -
                # @raise [Errors::RequiresCallable] if no  | 
| 35 | 
            +
                # @raise [Errors::RequiresCallable] if no block is provided
         | 
| 44 36 | 
             
                # @raise [Errors::InvalidName] if the name is not a symbol, cannot be converted to a symbol,
         | 
| 45 37 | 
             
                #                              or is not a valid attribute name
         | 
| 46 38 | 
             
                # @raise [Errors::AlreadyRegistered] if the name has been registered previously
         | 
| 47 39 | 
             
                #
         | 
| 48 40 | 
             
                # @since 0.1.0
         | 
| 49 | 
            -
                def transient(name,  | 
| 50 | 
            -
                   | 
| 41 | 
            +
                def transient(name, &block)
         | 
| 42 | 
            +
                  register_blueprint(name, :transient, &block)
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                # Register an instance dependency.
         | 
| 46 | 
            +
                #
         | 
| 47 | 
            +
                # An instance dependency gets created once for each instance of a dependent class.
         | 
| 48 | 
            +
                #
         | 
| 49 | 
            +
                # @example With a block
         | 
| 50 | 
            +
                #   manufacturer.instance(:sha1_hasher) { Digest::SHA1.new }
         | 
| 51 | 
            +
                #
         | 
| 52 | 
            +
                # @example With a Proc
         | 
| 53 | 
            +
                #   manufacturer.instance(:sha1_hasher, &-> { Digest::SHA1.new })
         | 
| 54 | 
            +
                #
         | 
| 55 | 
            +
                # @param name [Symbol, #to_sym] the dependency name which will be used to access it
         | 
| 56 | 
            +
                # @param block [Block, Proc] a factory method to build the dependency
         | 
| 57 | 
            +
                #
         | 
| 58 | 
            +
                # @raise [Errors::RequiresCallable] if no block is provided
         | 
| 59 | 
            +
                # @raise [Errors::InvalidName] if the name is not a symbol, cannot be converted to a symbol,
         | 
| 60 | 
            +
                #                              or is not a valid attribute name
         | 
| 61 | 
            +
                # @raise [Errors::AlreadyRegistered] if the name has been registered previously
         | 
| 62 | 
            +
                #
         | 
| 63 | 
            +
                # @since 0.3.0
         | 
| 64 | 
            +
                def instance(name, &block)
         | 
| 65 | 
            +
                  register_blueprint(name, :instance, &block)
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                # Register a singleton dependency.
         | 
| 69 | 
            +
                #
         | 
| 70 | 
            +
                # A singleton dependency gets created once.
         | 
| 71 | 
            +
                #
         | 
| 72 | 
            +
                # @example With a block
         | 
| 73 | 
            +
                #   manufacturer.singleton(:sha1_hasher) { Digest::SHA1.new }
         | 
| 74 | 
            +
                #
         | 
| 75 | 
            +
                # @example With a Proc
         | 
| 76 | 
            +
                #   manufacturer.singleton(:sha1_hasher, &-> { Digest::SHA1.new })
         | 
| 77 | 
            +
                #
         | 
| 78 | 
            +
                # @param name [Symbol, #to_sym] the dependency name which will be used to access it
         | 
| 79 | 
            +
                # @param block [Block, Proc] a factory method to build the dependency
         | 
| 80 | 
            +
                #
         | 
| 81 | 
            +
                # @raise [Errors::RequiresCallable] if no block is provided
         | 
| 82 | 
            +
                # @raise [Errors::InvalidName] if the name is not a symbol, cannot be converted to a symbol,
         | 
| 83 | 
            +
                #                              or is not a valid attribute name
         | 
| 84 | 
            +
                # @raise [Errors::AlreadyRegistered] if the name has been registered previously
         | 
| 85 | 
            +
                #
         | 
| 86 | 
            +
                # @since 0.4.0
         | 
| 87 | 
            +
                def singleton(name, &block)
         | 
| 88 | 
            +
                  register_blueprint(name, :singleton, &block)
         | 
| 89 | 
            +
                end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                private
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                def register_blueprint(name, lifecycle, &block)
         | 
| 94 | 
            +
                  validate_dependency_name name
         | 
| 51 95 | 
             
                  raise Errors::AlreadyRegistered if @registered_blueprints.has_key? name
         | 
| 52 | 
            -
                  raise Errors::RequiresCallable  | 
| 96 | 
            +
                  raise Errors::RequiresCallable if block.nil?
         | 
| 53 97 |  | 
| 54 98 | 
             
                  blueprint_name = name.to_sym
         | 
| 55 99 | 
             
                  @registered_blueprints[blueprint_name] = {
         | 
| 56 | 
            -
                    lifecycle:  | 
| 57 | 
            -
                     | 
| 58 | 
            -
                    accessor_module: build_module(blueprint_name,  | 
| 100 | 
            +
                    lifecycle: lifecycle,
         | 
| 101 | 
            +
                    factory: block,
         | 
| 102 | 
            +
                    accessor_module: build_module(blueprint_name, lifecycle, block)
         | 
| 59 103 | 
             
                  }
         | 
| 60 104 | 
             
                end
         | 
| 61 105 |  | 
| 62 | 
            -
                 | 
| 106 | 
            +
                def build_module(name, lifecycle, factory)
         | 
| 107 | 
            +
                  module_name = "I#{hash_name(name)}"
         | 
| 108 | 
            +
                  module_body =
         | 
| 109 | 
            +
                    case lifecycle
         | 
| 110 | 
            +
                    when :transient then build_transient(name, factory)
         | 
| 111 | 
            +
                    when :instance then build_instance(name, factory)
         | 
| 112 | 
            +
                    when :singleton then build_singleton(name, factory)
         | 
| 113 | 
            +
                    else raise ArgumentError, "Life cycle #{lifecycle} is not valid. Something has gone very wrong."
         | 
| 114 | 
            +
                    end
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  Providers.module_eval { const_set(module_name, module_body) }
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                def build_transient(name, factory)
         | 
| 120 | 
            +
                  Module.new do
         | 
| 121 | 
            +
                    private define_method(name) { factory.call }
         | 
| 122 | 
            +
                  end
         | 
| 123 | 
            +
                end
         | 
| 63 124 |  | 
| 64 | 
            -
                def  | 
| 65 | 
            -
                   | 
| 66 | 
            -
                   | 
| 67 | 
            -
                     | 
| 68 | 
            -
                       | 
| 69 | 
            -
             | 
| 125 | 
            +
                def build_instance(name, factory)
         | 
| 126 | 
            +
                  cache_variable_name = "@icache_#{hash_name(name)}"
         | 
| 127 | 
            +
                  Module.new do
         | 
| 128 | 
            +
                    define_method(name) do
         | 
| 129 | 
            +
                      instance_variable_set(cache_variable_name, factory.call) unless instance_variable_defined?(cache_variable_name)
         | 
| 130 | 
            +
                      instance_variable_get(cache_variable_name)
         | 
| 131 | 
            +
                    end
         | 
| 132 | 
            +
                    private name
         | 
| 70 133 | 
             
                  end
         | 
| 71 134 | 
             
                end
         | 
| 72 135 |  | 
| 73 | 
            -
                def  | 
| 136 | 
            +
                def build_singleton(name, factory)
         | 
| 137 | 
            +
                  cache_variable_name = "@@icache_#{hash_name(name)}"
         | 
| 138 | 
            +
                  Module.new do |mod|
         | 
| 139 | 
            +
                    define_method(name) do
         | 
| 140 | 
            +
                      mod.class_variable_set(cache_variable_name, factory.call) unless mod.class_variable_defined?(cache_variable_name)
         | 
| 141 | 
            +
                      mod.class_variable_get(cache_variable_name)
         | 
| 142 | 
            +
                    end
         | 
| 143 | 
            +
                    private name
         | 
| 144 | 
            +
                  end
         | 
| 145 | 
            +
                end
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                def validate_dependency_name(name)
         | 
| 74 148 | 
             
                  raise Errors::InvalidName, "name must be a symbol or convert to one" unless name.respond_to? :to_sym
         | 
| 75 149 | 
             
                  begin
         | 
| 76 150 | 
             
                    Module.new { attr_reader name }
         | 
| @@ -78,5 +152,9 @@ module Inoculate | |
| 78 152 | 
             
                    raise Errors::InvalidName, "name must be a valid attr_reader"
         | 
| 79 153 | 
             
                  end
         | 
| 80 154 | 
             
                end
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                def hash_name(name)
         | 
| 157 | 
            +
                  Digest::SHA1.hexdigest(name.to_s)
         | 
| 158 | 
            +
                end
         | 
| 81 159 | 
             
              end
         | 
| 82 160 | 
             
            end
         | 
    
        data/lib/inoculate/version.rb
    CHANGED
    
    
    
        data/sig/inoculate.rbs
    CHANGED
    
    | @@ -6,9 +6,9 @@ module Inoculate | |
| 6 6 | 
             
              end
         | 
| 7 7 |  | 
| 8 8 | 
             
              type callable = ^() -> untyped
         | 
| 9 | 
            -
              type lifecycle_name = :transient
         | 
| 9 | 
            +
              type lifecycle_name = :transient | :instance
         | 
| 10 10 | 
             
              type builder_name = Symbol
         | 
| 11 | 
            -
              type blueprint = { lifecycle: lifecycle_name,  | 
| 11 | 
            +
              type blueprint = { lifecycle: lifecycle_name, factory: callable, accessor_module: Module? }
         | 
| 12 12 |  | 
| 13 13 | 
             
              module Errors
         | 
| 14 14 | 
             
                class Error < StandardError
         | 
| @@ -32,13 +32,17 @@ module Inoculate | |
| 32 32 |  | 
| 33 33 | 
             
              class Manufacturer
         | 
| 34 34 | 
             
                attr_reader registered_blueprints: Hash[builder_name, blueprint]
         | 
| 35 | 
            -
                def transient: (builder_name | _ToSymbol | 
| 35 | 
            +
                def transient: (builder_name | _ToSymbol) { () -> void } -> void
         | 
| 36 | 
            +
                def instance: (builder_name | _ToSymbol) { () -> void } -> void
         | 
| 37 | 
            +
                def singleton: (builder_name | _ToSymbol) { () -> void } -> void
         | 
| 36 38 | 
             
              end
         | 
| 37 39 |  | 
| 38 40 | 
             
              class Configurer
         | 
| 39 41 | 
             
                def initialize: (Manufacturer) -> void
         | 
| 40 42 |  | 
| 41 | 
            -
                def transient: (builder_name | _ToSymbol | 
| 43 | 
            +
                def transient: (builder_name | _ToSymbol) { () -> void } -> nil
         | 
| 44 | 
            +
                def instance: (builder_name | _ToSymbol) { () -> void } -> nil
         | 
| 45 | 
            +
                def singleton: (builder_name | _ToSymbol) { () -> void } -> nil
         | 
| 42 46 |  | 
| 43 47 | 
             
                private
         | 
| 44 48 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: inoculate
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.4.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Stephan Tarulli
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022-10- | 
| 11 | 
            +
            date: 2022-10-13 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description: |
         | 
| 14 14 | 
             
              Inoculate is a small, thread-safe dependency injection library configured entirely with Ruby.
         |