rom 3.0.0.rc1 → 3.0.0.rc2
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/lib/rom/command.rb +281 -31
 - data/lib/rom/container.rb +11 -15
 - data/lib/rom/gateway.rb +51 -26
 - data/lib/rom/relation.rb +44 -6
 - data/lib/rom/version.rb +1 -1
 - data/spec/unit/rom/commands/pre_and_post_processors_spec.rb +49 -1
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: c09afbd9407f30670628cfcfaebf9d903ca6619c
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: a94d330cd2a0ecb12c500042b9659ec5ee48c568
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: cf5b188aca3186e6f402f4e246edc6555821fb0d0a24e771715267806a923fd3bd19ec4a0270a572b4fd7c48ee8d9ff380a2aca407202d6d84c1846f884b81e7
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 552d6f7c1436ae873f1926feafd38f218090ec3ba0a109b45fa931eb3578452f4611745426adb2fbeca537c9ed36ba66c4b99b5ac00faf815e0e17a921811039
         
     | 
    
        data/lib/rom/command.rb
    CHANGED
    
    | 
         @@ -21,7 +21,7 @@ module ROM 
     | 
|
| 
       21 
21 
     | 
    
         
             
              #
         
     | 
| 
       22 
22 
     | 
    
         
             
              # @abstract
         
     | 
| 
       23 
23 
     | 
    
         
             
              #
         
     | 
| 
       24 
     | 
    
         
            -
              # @ 
     | 
| 
      
 24 
     | 
    
         
            +
              # @api public
         
     | 
| 
       25 
25 
     | 
    
         
             
              class Command
         
     | 
| 
       26 
26 
     | 
    
         
             
                extend Initializer
         
     | 
| 
       27 
27 
     | 
    
         
             
                include Dry::Equalizer(:relation, :options)
         
     | 
| 
         @@ -31,20 +31,199 @@ module ROM 
     | 
|
| 
       31 
31 
     | 
    
         
             
                extend Dry::Core::ClassAttributes
         
     | 
| 
       32 
32 
     | 
    
         
             
                extend ClassInterface
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                 
     | 
| 
      
 34 
     | 
    
         
            +
                # @!method self.adapter
         
     | 
| 
      
 35 
     | 
    
         
            +
                #   Get or set adapter identifier
         
     | 
| 
      
 36 
     | 
    
         
            +
                #
         
     | 
| 
      
 37 
     | 
    
         
            +
                #   @overload adapter
         
     | 
| 
      
 38 
     | 
    
         
            +
                #     Get adapter identifier
         
     | 
| 
      
 39 
     | 
    
         
            +
                #
         
     | 
| 
      
 40 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 41 
     | 
    
         
            +
                #       ROM::Memory::Commands::Create.adapter
         
     | 
| 
      
 42 
     | 
    
         
            +
                #       # => :memory
         
     | 
| 
      
 43 
     | 
    
         
            +
                #
         
     | 
| 
      
 44 
     | 
    
         
            +
                #     @return [Symbol]
         
     | 
| 
      
 45 
     | 
    
         
            +
                #
         
     | 
| 
      
 46 
     | 
    
         
            +
                #   @overload adapter(identifier)
         
     | 
| 
      
 47 
     | 
    
         
            +
                #     Set adapter identifier. This must always match actual adapter identifier
         
     | 
| 
      
 48 
     | 
    
         
            +
                #     that was used to register an adapter.
         
     | 
| 
      
 49 
     | 
    
         
            +
                #
         
     | 
| 
      
 50 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 51 
     | 
    
         
            +
                #       module MyAdapter
         
     | 
| 
      
 52 
     | 
    
         
            +
                #         class CreateCommand < ROM::Commands::Memory::Create
         
     | 
| 
      
 53 
     | 
    
         
            +
                #           adapter :my_adapter
         
     | 
| 
      
 54 
     | 
    
         
            +
                #         end
         
     | 
| 
      
 55 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 56 
     | 
    
         
            +
                #
         
     | 
| 
      
 57 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 58 
     | 
    
         
            +
                defines :adapter
         
     | 
| 
       35 
59 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
                #  
     | 
| 
      
 60 
     | 
    
         
            +
                # @!method self.relation
         
     | 
| 
      
 61 
     | 
    
         
            +
                #   Get or set relation identifier
         
     | 
| 
      
 62 
     | 
    
         
            +
                #
         
     | 
| 
      
 63 
     | 
    
         
            +
                #   @overload relation
         
     | 
| 
      
 64 
     | 
    
         
            +
                #     Get relation identifier
         
     | 
| 
      
 65 
     | 
    
         
            +
                #
         
     | 
| 
      
 66 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 67 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 68 
     | 
    
         
            +
                #         relation :users
         
     | 
| 
      
 69 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 70 
     | 
    
         
            +
                #
         
     | 
| 
      
 71 
     | 
    
         
            +
                #       CreateUser.relation
         
     | 
| 
      
 72 
     | 
    
         
            +
                #       # => :users
         
     | 
| 
      
 73 
     | 
    
         
            +
                #
         
     | 
| 
      
 74 
     | 
    
         
            +
                #     @return [Symbol]
         
     | 
| 
      
 75 
     | 
    
         
            +
                #
         
     | 
| 
      
 76 
     | 
    
         
            +
                #   @overload relation(identifier)
         
     | 
| 
      
 77 
     | 
    
         
            +
                #     Set relation identifier.
         
     | 
| 
      
 78 
     | 
    
         
            +
                #
         
     | 
| 
      
 79 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 80 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 81 
     | 
    
         
            +
                #         relation :users
         
     | 
| 
      
 82 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 83 
     | 
    
         
            +
                #
         
     | 
| 
      
 84 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 85 
     | 
    
         
            +
                defines :relation
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                # @!method self.relation
         
     | 
| 
      
 88 
     | 
    
         
            +
                #   Get or set result type
         
     | 
| 
      
 89 
     | 
    
         
            +
                #
         
     | 
| 
      
 90 
     | 
    
         
            +
                #   @overload result
         
     | 
| 
      
 91 
     | 
    
         
            +
                #     Get result type
         
     | 
| 
      
 92 
     | 
    
         
            +
                #
         
     | 
| 
      
 93 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 94 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 95 
     | 
    
         
            +
                #         result :one
         
     | 
| 
      
 96 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 97 
     | 
    
         
            +
                #
         
     | 
| 
      
 98 
     | 
    
         
            +
                #       CreateUser.result
         
     | 
| 
      
 99 
     | 
    
         
            +
                #       # => :one
         
     | 
| 
      
 100 
     | 
    
         
            +
                #
         
     | 
| 
      
 101 
     | 
    
         
            +
                #     @return [Symbol]
         
     | 
| 
      
 102 
     | 
    
         
            +
                #
         
     | 
| 
      
 103 
     | 
    
         
            +
                #   @overload relation(identifier)
         
     | 
| 
      
 104 
     | 
    
         
            +
                #     Set result type
         
     | 
| 
      
 105 
     | 
    
         
            +
                #
         
     | 
| 
      
 106 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 107 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 108 
     | 
    
         
            +
                #         result :one
         
     | 
| 
      
 109 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 110 
     | 
    
         
            +
                #
         
     | 
| 
      
 111 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 112 
     | 
    
         
            +
                defines :result
         
     | 
| 
      
 113 
     | 
    
         
            +
             
     | 
| 
      
 114 
     | 
    
         
            +
                # @!method self.relation
         
     | 
| 
      
 115 
     | 
    
         
            +
                #   Get or set input processing function. This is typically set during setup
         
     | 
| 
      
 116 
     | 
    
         
            +
                #   to relation's input_schema
         
     | 
| 
      
 117 
     | 
    
         
            +
                #
         
     | 
| 
      
 118 
     | 
    
         
            +
                #   @overload input
         
     | 
| 
      
 119 
     | 
    
         
            +
                #     Get input processing function
         
     | 
| 
      
 120 
     | 
    
         
            +
                #
         
     | 
| 
      
 121 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 122 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 123 
     | 
    
         
            +
                #         input -> tuple { .. }
         
     | 
| 
      
 124 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 125 
     | 
    
         
            +
                #
         
     | 
| 
      
 126 
     | 
    
         
            +
                #       CreateUser.input
         
     | 
| 
      
 127 
     | 
    
         
            +
                #       # Your custom function
         
     | 
| 
      
 128 
     | 
    
         
            +
                #
         
     | 
| 
      
 129 
     | 
    
         
            +
                #     @return [Proc,#call]
         
     | 
| 
      
 130 
     | 
    
         
            +
                #
         
     | 
| 
      
 131 
     | 
    
         
            +
                #   @overload input(identifier)
         
     | 
| 
      
 132 
     | 
    
         
            +
                #     Set input processing function
         
     | 
| 
      
 133 
     | 
    
         
            +
                #
         
     | 
| 
      
 134 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 135 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 136 
     | 
    
         
            +
                #         input -> tuple { .. }
         
     | 
| 
      
 137 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 138 
     | 
    
         
            +
                #
         
     | 
| 
      
 139 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 140 
     | 
    
         
            +
                defines :input
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                # @!method self.register_as
         
     | 
| 
      
 143 
     | 
    
         
            +
                #   Get or set identifier that should be used to register a command in a container
         
     | 
| 
      
 144 
     | 
    
         
            +
                #
         
     | 
| 
      
 145 
     | 
    
         
            +
                #   @overload register_as
         
     | 
| 
      
 146 
     | 
    
         
            +
                #     Get registration identifier
         
     | 
| 
      
 147 
     | 
    
         
            +
                #
         
     | 
| 
      
 148 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 149 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 150 
     | 
    
         
            +
                #         register_as :create_user
         
     | 
| 
      
 151 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 152 
     | 
    
         
            +
                #
         
     | 
| 
      
 153 
     | 
    
         
            +
                #       CreateUser.register_as
         
     | 
| 
      
 154 
     | 
    
         
            +
                #       # => :create_user
         
     | 
| 
      
 155 
     | 
    
         
            +
                #
         
     | 
| 
      
 156 
     | 
    
         
            +
                #     @return [Symbol]
         
     | 
| 
      
 157 
     | 
    
         
            +
                #
         
     | 
| 
      
 158 
     | 
    
         
            +
                #   @overload register_as(identifier)
         
     | 
| 
      
 159 
     | 
    
         
            +
                #     Set registration identifier
         
     | 
| 
      
 160 
     | 
    
         
            +
                #
         
     | 
| 
      
 161 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 162 
     | 
    
         
            +
                #       module CreateUser < ROM::Commands::Create[:memory]
         
     | 
| 
      
 163 
     | 
    
         
            +
                #         register_as :create_user
         
     | 
| 
      
 164 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 165 
     | 
    
         
            +
                #
         
     | 
| 
      
 166 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 167 
     | 
    
         
            +
                defines :register_as
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                # @!method self.restrictable
         
     | 
| 
      
 170 
     | 
    
         
            +
                #   @overload restrictable
         
     | 
| 
      
 171 
     | 
    
         
            +
                #     Check if a command class is restrictable
         
     | 
| 
      
 172 
     | 
    
         
            +
                #
         
     | 
| 
      
 173 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 174 
     | 
    
         
            +
                #       module UpdateUser < ROM::Commands::Update[:memory]
         
     | 
| 
      
 175 
     | 
    
         
            +
                #         restrictable true
         
     | 
| 
      
 176 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 177 
     | 
    
         
            +
                #
         
     | 
| 
      
 178 
     | 
    
         
            +
                #       CreateUser.restrictable
         
     | 
| 
      
 179 
     | 
    
         
            +
                #       # => true
         
     | 
| 
      
 180 
     | 
    
         
            +
                #
         
     | 
| 
      
 181 
     | 
    
         
            +
                #     @return [FalseClass, TrueClass]
         
     | 
| 
      
 182 
     | 
    
         
            +
                #
         
     | 
| 
      
 183 
     | 
    
         
            +
                #   @overload restrictable(value)
         
     | 
| 
      
 184 
     | 
    
         
            +
                #     Set if a command is restrictable
         
     | 
| 
      
 185 
     | 
    
         
            +
                #
         
     | 
| 
      
 186 
     | 
    
         
            +
                #     @example
         
     | 
| 
      
 187 
     | 
    
         
            +
                #       module UpdateUser < ROM::Commands::Update[:memory]
         
     | 
| 
      
 188 
     | 
    
         
            +
                #         restrictable true
         
     | 
| 
      
 189 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 190 
     | 
    
         
            +
                #
         
     | 
| 
      
 191 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 192 
     | 
    
         
            +
                defines :restrictable
         
     | 
| 
      
 193 
     | 
    
         
            +
             
     | 
| 
      
 194 
     | 
    
         
            +
                # @!attribute [r] relation
         
     | 
| 
      
 195 
     | 
    
         
            +
                #   @return [Relation] Command's relation
         
     | 
| 
       37 
196 
     | 
    
         
             
                param :relation
         
     | 
| 
       38 
197 
     | 
    
         | 
| 
       39 
198 
     | 
    
         
             
                CommandType = Types::Strict::Symbol.enum(:create, :update, :delete)
         
     | 
| 
       40 
199 
     | 
    
         
             
                Result = Types::Strict::Symbol.enum(:one, :many)
         
     | 
| 
       41 
200 
     | 
    
         | 
| 
      
 201 
     | 
    
         
            +
                # @!attribute [r] type
         
     | 
| 
      
 202 
     | 
    
         
            +
                #   @return [Symbol] The command type, one of :create, :update or :delete
         
     | 
| 
       42 
203 
     | 
    
         
             
                option :type, type: CommandType, optional: true
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                # @!attribute [r] source
         
     | 
| 
      
 206 
     | 
    
         
            +
                #   @return [Relation] The source relation
         
     | 
| 
       43 
207 
     | 
    
         
             
                option :source, reader: true, optional: true, default: -> c { c.relation }
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                # @!attribute [r] type
         
     | 
| 
      
 210 
     | 
    
         
            +
                #   @return [Symbol] Result type, either :one or :many
         
     | 
| 
       44 
211 
     | 
    
         
             
                option :result, reader: true, type: Result
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                # @!attribute [r] input
         
     | 
| 
      
 214 
     | 
    
         
            +
                #   @return [Proc, #call] Tuple processing function, typically uses Relation#input_schema
         
     | 
| 
       45 
215 
     | 
    
         
             
                option :input, reader: true
         
     | 
| 
      
 216 
     | 
    
         
            +
             
     | 
| 
      
 217 
     | 
    
         
            +
                # @!attribute [r] curry_args
         
     | 
| 
      
 218 
     | 
    
         
            +
                #   @return [Array] Curried args
         
     | 
| 
       46 
219 
     | 
    
         
             
                option :curry_args, reader: true, default: -> _ { EMPTY_ARRAY }
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                # @!attribute [r] before
         
     | 
| 
      
 222 
     | 
    
         
            +
                #   @return [Array<Hash>] An array with before hooks configuration
         
     | 
| 
       47 
223 
     | 
    
         
             
                option :before, Types::Coercible::Array, reader: true, as: :before_hooks, default: proc { EMPTY_ARRAY }
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                # @!attribute [r] before
         
     | 
| 
      
 226 
     | 
    
         
            +
                #   @return [Array<Hash>] An array with after hooks configuration
         
     | 
| 
       48 
227 
     | 
    
         
             
                option :after, Types::Coercible::Array, reader: true, as: :after_hooks, default: proc { EMPTY_ARRAY }
         
     | 
| 
       49 
228 
     | 
    
         | 
| 
       50 
229 
     | 
    
         
             
                input Hash
         
     | 
| 
         @@ -84,6 +263,8 @@ module ROM 
     | 
|
| 
       84 
263 
     | 
    
         | 
| 
       85 
264 
     | 
    
         
             
                # Call the command and return one or many tuples
         
     | 
| 
       86 
265 
     | 
    
         
             
                #
         
     | 
| 
      
 266 
     | 
    
         
            +
                # This method will apply before/after hooks automatically
         
     | 
| 
      
 267 
     | 
    
         
            +
                #
         
     | 
| 
       87 
268 
     | 
    
         
             
                # @api public
         
     | 
| 
       88 
269 
     | 
    
         
             
                def call(*args, &block)
         
     | 
| 
       89 
270 
     | 
    
         
             
                  tuples =
         
     | 
| 
         @@ -98,7 +279,13 @@ module ROM 
     | 
|
| 
       98 
279 
     | 
    
         
             
                      result = prepared ? execute(prepared, &block) : execute(&block)
         
     | 
| 
       99 
280 
     | 
    
         | 
| 
       100 
281 
     | 
    
         
             
                      if curried?
         
     | 
| 
       101 
     | 
    
         
            -
                         
     | 
| 
      
 282 
     | 
    
         
            +
                        if args.size > 0
         
     | 
| 
      
 283 
     | 
    
         
            +
                          apply_hooks(after_hooks, result, *args)
         
     | 
| 
      
 284 
     | 
    
         
            +
                        elsif curry_args.size > 1
         
     | 
| 
      
 285 
     | 
    
         
            +
                          apply_hooks(after_hooks, result, curry_args[1])
         
     | 
| 
      
 286 
     | 
    
         
            +
                        else
         
     | 
| 
      
 287 
     | 
    
         
            +
                          apply_hooks(after_hooks, result)
         
     | 
| 
      
 288 
     | 
    
         
            +
                        end
         
     | 
| 
       102 
289 
     | 
    
         
             
                      else
         
     | 
| 
       103 
290 
     | 
    
         
             
                        apply_hooks(after_hooks, result, *args[1..args.size-1])
         
     | 
| 
       104 
291 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -116,9 +303,10 @@ module ROM 
     | 
|
| 
       116 
303 
     | 
    
         | 
| 
       117 
304 
     | 
    
         
             
                # Curry this command with provided args
         
     | 
| 
       118 
305 
     | 
    
         
             
                #
         
     | 
| 
       119 
     | 
    
         
            -
                # Curried command can be called without args
         
     | 
| 
      
 306 
     | 
    
         
            +
                # Curried command can be called without args. If argument is a graph input processor,
         
     | 
| 
      
 307 
     | 
    
         
            +
                # lazy command will be returned, which is used for handling nested input hashes.
         
     | 
| 
       120 
308 
     | 
    
         
             
                #
         
     | 
| 
       121 
     | 
    
         
            -
                # @return [Command]
         
     | 
| 
      
 309 
     | 
    
         
            +
                # @return [Command, Lazy]
         
     | 
| 
       122 
310 
     | 
    
         
             
                #
         
     | 
| 
       123 
311 
     | 
    
         
             
                # @api public
         
     | 
| 
       124 
312 
     | 
    
         
             
                def curry(*args)
         
     | 
| 
         @@ -130,68 +318,130 @@ module ROM 
     | 
|
| 
       130 
318 
     | 
    
         
             
                end
         
     | 
| 
       131 
319 
     | 
    
         
             
                alias_method :with, :curry
         
     | 
| 
       132 
320 
     | 
    
         | 
| 
      
 321 
     | 
    
         
            +
                # Compose this command with other commands
         
     | 
| 
      
 322 
     | 
    
         
            +
                #
         
     | 
| 
      
 323 
     | 
    
         
            +
                # Composed commands can handle nested input
         
     | 
| 
      
 324 
     | 
    
         
            +
                #
         
     | 
| 
      
 325 
     | 
    
         
            +
                # @return [Command::Graph]
         
     | 
| 
      
 326 
     | 
    
         
            +
                #
         
     | 
| 
      
 327 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 328 
     | 
    
         
            +
                def combine(*others)
         
     | 
| 
      
 329 
     | 
    
         
            +
                  Graph.new(self, others)
         
     | 
| 
      
 330 
     | 
    
         
            +
                end
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
      
 332 
     | 
    
         
            +
                # Check if this command is curried
         
     | 
| 
      
 333 
     | 
    
         
            +
                #
         
     | 
| 
      
 334 
     | 
    
         
            +
                # @return [TrueClass, FalseClass]
         
     | 
| 
      
 335 
     | 
    
         
            +
                #
         
     | 
| 
       133 
336 
     | 
    
         
             
                # @api public
         
     | 
| 
       134 
337 
     | 
    
         
             
                def curried?
         
     | 
| 
       135 
338 
     | 
    
         
             
                  curry_args.size > 0
         
     | 
| 
       136 
339 
     | 
    
         
             
                end
         
     | 
| 
       137 
340 
     | 
    
         | 
| 
       138 
     | 
    
         
            -
                #  
     | 
| 
       139 
     | 
    
         
            -
                 
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
      
 341 
     | 
    
         
            +
                # Return a new command with new options
         
     | 
| 
      
 342 
     | 
    
         
            +
                #
         
     | 
| 
      
 343 
     | 
    
         
            +
                # @param [Hash] new_opts A hash with new options
         
     | 
| 
      
 344 
     | 
    
         
            +
                #
         
     | 
| 
      
 345 
     | 
    
         
            +
                # @return [Command]
         
     | 
| 
      
 346 
     | 
    
         
            +
                #
         
     | 
| 
      
 347 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 348 
     | 
    
         
            +
                def with_opts(new_opts)
         
     | 
| 
      
 349 
     | 
    
         
            +
                  self.class.new(relation, options.merge(new_opts))
         
     | 
| 
       141 
350 
     | 
    
         
             
                end
         
     | 
| 
       142 
351 
     | 
    
         | 
| 
      
 352 
     | 
    
         
            +
                # Return a new command with appended before hooks
         
     | 
| 
      
 353 
     | 
    
         
            +
                #
         
     | 
| 
      
 354 
     | 
    
         
            +
                # @param [Array<Hash>] hooks A list of before hooks configurations
         
     | 
| 
      
 355 
     | 
    
         
            +
                #
         
     | 
| 
      
 356 
     | 
    
         
            +
                # @return [Command]
         
     | 
| 
      
 357 
     | 
    
         
            +
                #
         
     | 
| 
       143 
358 
     | 
    
         
             
                # @api public
         
     | 
| 
       144 
     | 
    
         
            -
                def  
     | 
| 
       145 
     | 
    
         
            -
                   
     | 
| 
      
 359 
     | 
    
         
            +
                def before(*hooks)
         
     | 
| 
      
 360 
     | 
    
         
            +
                  self.class.new(relation, options.merge(before: before_hooks + hooks))
         
     | 
| 
       146 
361 
     | 
    
         
             
                end
         
     | 
| 
       147 
362 
     | 
    
         | 
| 
      
 363 
     | 
    
         
            +
                # Return a new command with appended after hooks
         
     | 
| 
      
 364 
     | 
    
         
            +
                #
         
     | 
| 
      
 365 
     | 
    
         
            +
                # @param [Array<Hash>] hooks A list of after hooks configurations
         
     | 
| 
      
 366 
     | 
    
         
            +
                #
         
     | 
| 
      
 367 
     | 
    
         
            +
                # @return [Command]
         
     | 
| 
      
 368 
     | 
    
         
            +
                #
         
     | 
| 
      
 369 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 370 
     | 
    
         
            +
                def after(*hooks)
         
     | 
| 
      
 371 
     | 
    
         
            +
                  self.class.new(relation, options.merge(after: after_hooks + hooks))
         
     | 
| 
      
 372 
     | 
    
         
            +
                end
         
     | 
| 
      
 373 
     | 
    
         
            +
             
     | 
| 
      
 374 
     | 
    
         
            +
                # Return a new command with other source relation
         
     | 
| 
      
 375 
     | 
    
         
            +
                #
         
     | 
| 
      
 376 
     | 
    
         
            +
                # This can be used to restrict command with a specific relation
         
     | 
| 
      
 377 
     | 
    
         
            +
                #
         
     | 
| 
      
 378 
     | 
    
         
            +
                # @return [Command]
         
     | 
| 
      
 379 
     | 
    
         
            +
                #
         
     | 
| 
      
 380 
     | 
    
         
            +
                # @api public
         
     | 
| 
      
 381 
     | 
    
         
            +
                def new(new_relation)
         
     | 
| 
      
 382 
     | 
    
         
            +
                  self.class.build(new_relation, options.merge(source: relation))
         
     | 
| 
      
 383 
     | 
    
         
            +
                end
         
     | 
| 
      
 384 
     | 
    
         
            +
             
     | 
| 
      
 385 
     | 
    
         
            +
                # Check if this command has any hooks
         
     | 
| 
      
 386 
     | 
    
         
            +
                #
         
     | 
| 
      
 387 
     | 
    
         
            +
                # @api private
         
     | 
| 
      
 388 
     | 
    
         
            +
                def hooks?
         
     | 
| 
      
 389 
     | 
    
         
            +
                  before_hooks.size > 0 || after_hooks.size > 0
         
     | 
| 
      
 390 
     | 
    
         
            +
                end
         
     | 
| 
      
 391 
     | 
    
         
            +
             
     | 
| 
      
 392 
     | 
    
         
            +
                # Check if this command is lazy
         
     | 
| 
      
 393 
     | 
    
         
            +
                #
         
     | 
| 
      
 394 
     | 
    
         
            +
                # @return [false]
         
     | 
| 
      
 395 
     | 
    
         
            +
                #
         
     | 
| 
       148 
396 
     | 
    
         
             
                # @api private
         
     | 
| 
       149 
397 
     | 
    
         
             
                def lazy?
         
     | 
| 
       150 
398 
     | 
    
         
             
                  false
         
     | 
| 
       151 
399 
     | 
    
         
             
                end
         
     | 
| 
       152 
400 
     | 
    
         | 
| 
      
 401 
     | 
    
         
            +
                # Check if this command is a graph
         
     | 
| 
      
 402 
     | 
    
         
            +
                #
         
     | 
| 
      
 403 
     | 
    
         
            +
                # @return [false]
         
     | 
| 
      
 404 
     | 
    
         
            +
                #
         
     | 
| 
       153 
405 
     | 
    
         
             
                # @api private
         
     | 
| 
       154 
406 
     | 
    
         
             
                def graph?
         
     | 
| 
       155 
407 
     | 
    
         
             
                  false
         
     | 
| 
       156 
408 
     | 
    
         
             
                end
         
     | 
| 
       157 
409 
     | 
    
         | 
| 
      
 410 
     | 
    
         
            +
                # Check if this command returns a single tuple
         
     | 
| 
      
 411 
     | 
    
         
            +
                #
         
     | 
| 
      
 412 
     | 
    
         
            +
                # @return [TrueClass,FalseClass]
         
     | 
| 
      
 413 
     | 
    
         
            +
                #
         
     | 
| 
       158 
414 
     | 
    
         
             
                # @api private
         
     | 
| 
       159 
415 
     | 
    
         
             
                def one?
         
     | 
| 
       160 
416 
     | 
    
         
             
                  result.equal?(:one)
         
     | 
| 
       161 
417 
     | 
    
         
             
                end
         
     | 
| 
       162 
418 
     | 
    
         | 
| 
      
 419 
     | 
    
         
            +
                # Check if this command returns many tuples
         
     | 
| 
      
 420 
     | 
    
         
            +
                #
         
     | 
| 
      
 421 
     | 
    
         
            +
                # @return [TrueClass,FalseClass]
         
     | 
| 
      
 422 
     | 
    
         
            +
                #
         
     | 
| 
       163 
423 
     | 
    
         
             
                # @api private
         
     | 
| 
       164 
424 
     | 
    
         
             
                def many?
         
     | 
| 
       165 
425 
     | 
    
         
             
                  result.equal?(:many)
         
     | 
| 
       166 
426 
     | 
    
         
             
                end
         
     | 
| 
       167 
427 
     | 
    
         | 
| 
       168 
     | 
    
         
            -
                # @api private
         
     | 
| 
       169 
     | 
    
         
            -
                def new(new_relation)
         
     | 
| 
       170 
     | 
    
         
            -
                  self.class.build(new_relation, options.merge(source: relation))
         
     | 
| 
       171 
     | 
    
         
            -
                end
         
     | 
| 
       172 
     | 
    
         
            -
             
     | 
| 
       173 
     | 
    
         
            -
                # @api public
         
     | 
| 
       174 
     | 
    
         
            -
                def with_opts(new_opts)
         
     | 
| 
       175 
     | 
    
         
            -
                  self.class.new(relation, options.merge(new_opts))
         
     | 
| 
       176 
     | 
    
         
            -
                end
         
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
                # @api public
         
     | 
| 
       179 
     | 
    
         
            -
                def before(*hooks)
         
     | 
| 
       180 
     | 
    
         
            -
                  self.class.new(relation, options.merge(before: before_hooks + hooks))
         
     | 
| 
       181 
     | 
    
         
            -
                end
         
     | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
       183 
     | 
    
         
            -
                # @api public
         
     | 
| 
       184 
     | 
    
         
            -
                def after(*hooks)
         
     | 
| 
       185 
     | 
    
         
            -
                  self.class.new(relation, options.merge(after: after_hooks + hooks))
         
     | 
| 
       186 
     | 
    
         
            -
                end
         
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
428 
     | 
    
         
             
                private
         
     | 
| 
       189 
429 
     | 
    
         | 
| 
      
 430 
     | 
    
         
            +
                # Hook called by Pipeline to get composite class for commands
         
     | 
| 
      
 431 
     | 
    
         
            +
                #
         
     | 
| 
      
 432 
     | 
    
         
            +
                # @return [Class]
         
     | 
| 
      
 433 
     | 
    
         
            +
                #
         
     | 
| 
       190 
434 
     | 
    
         
             
                # @api private
         
     | 
| 
       191 
435 
     | 
    
         
             
                def composite_class
         
     | 
| 
       192 
436 
     | 
    
         
             
                  Command::Composite
         
     | 
| 
       193 
437 
     | 
    
         
             
                end
         
     | 
| 
       194 
438 
     | 
    
         | 
| 
      
 439 
     | 
    
         
            +
                # Apply provided hooks
         
     | 
| 
      
 440 
     | 
    
         
            +
                #
         
     | 
| 
      
 441 
     | 
    
         
            +
                # Used by #call
         
     | 
| 
      
 442 
     | 
    
         
            +
                #
         
     | 
| 
      
 443 
     | 
    
         
            +
                # @return [Array<Hash>]
         
     | 
| 
      
 444 
     | 
    
         
            +
                #
         
     | 
| 
       195 
445 
     | 
    
         
             
                # @api private
         
     | 
| 
       196 
446 
     | 
    
         
             
                def apply_hooks(hooks, tuples, *args)
         
     | 
| 
       197 
447 
     | 
    
         
             
                  hooks.reduce(tuples) do |a, e|
         
     | 
    
        data/lib/rom/container.rb
    CHANGED
    
    | 
         @@ -11,14 +11,14 @@ module ROM 
     | 
|
| 
       11 
11 
     | 
    
         
             
              #
         
     | 
| 
       12 
12 
     | 
    
         
             
              # There are 3 types of container setup:
         
     | 
| 
       13 
13 
     | 
    
         
             
              #
         
     | 
| 
       14 
     | 
    
         
            -
              # *  
     | 
| 
      
 14 
     | 
    
         
            +
              # * Setup DSL - a simple block-based configuration which allows configuring
         
     | 
| 
       15 
15 
     | 
    
         
             
              #   all components and gives you back a container instance. This type is suitable
         
     | 
| 
       16 
16 
     | 
    
         
             
              #   for small scripts, or in some cases rake tasks
         
     | 
| 
       17 
     | 
    
         
            -
              # *  
     | 
| 
      
 17 
     | 
    
         
            +
              # * Explicit setup - this type requires creating a configuration object,
         
     | 
| 
       18 
18 
     | 
    
         
             
              #   registering component classes (ie relation classes) and passing the config
         
     | 
| 
       19 
19 
     | 
    
         
             
              #   to container builder function. This type is suitable when your environment
         
     | 
| 
       20 
20 
     | 
    
         
             
              #   is not typical and you need full control over component registration
         
     | 
| 
       21 
     | 
    
         
            -
              # *  
     | 
| 
      
 21 
     | 
    
         
            +
              # * Explicit setup with auto-registration - same as explicit setup but allows
         
     | 
| 
       22 
22 
     | 
    
         
             
              #   you to configure auto-registration mechanism which will register component
         
     | 
| 
       23 
23 
     | 
    
         
             
              #   classes for you, based on dir/file naming conventions. This is the most
         
     | 
| 
       24 
24 
     | 
    
         
             
              #   common type of setup that's used by framework integrations
         
     | 
| 
         @@ -99,24 +99,20 @@ module ROM 
     | 
|
| 
       99 
99 
     | 
    
         
             
              class Container
         
     | 
| 
       100 
100 
     | 
    
         
             
                include Dry::Equalizer(:gateways, :relations, :mappers, :commands)
         
     | 
| 
       101 
101 
     | 
    
         | 
| 
       102 
     | 
    
         
            -
                #  
     | 
| 
       103 
     | 
    
         
            -
                #
         
     | 
| 
       104 
     | 
    
         
            -
                # @api public
         
     | 
| 
      
 102 
     | 
    
         
            +
                # @!attribute [r] gateways
         
     | 
| 
      
 103 
     | 
    
         
            +
                #   @return [Hash] A hash with configured gateways
         
     | 
| 
       105 
104 
     | 
    
         
             
                attr_reader :gateways
         
     | 
| 
       106 
105 
     | 
    
         | 
| 
       107 
     | 
    
         
            -
                #  
     | 
| 
       108 
     | 
    
         
            -
                #
         
     | 
| 
       109 
     | 
    
         
            -
                # @api public
         
     | 
| 
      
 106 
     | 
    
         
            +
                # @!attribute [r] relations
         
     | 
| 
      
 107 
     | 
    
         
            +
                #   @return [RelationRegistry] The relation registry
         
     | 
| 
       110 
108 
     | 
    
         
             
                attr_reader :relations
         
     | 
| 
       111 
109 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                #  
     | 
| 
       113 
     | 
    
         
            -
                #
         
     | 
| 
       114 
     | 
    
         
            -
                # @api public
         
     | 
| 
      
 110 
     | 
    
         
            +
                # @!attribute [r] gateways
         
     | 
| 
      
 111 
     | 
    
         
            +
                #   @return [CommandRegistry] The command registry
         
     | 
| 
       115 
112 
     | 
    
         
             
                attr_reader :commands
         
     | 
| 
       116 
113 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
                #  
     | 
| 
       118 
     | 
    
         
            -
                #
         
     | 
| 
       119 
     | 
    
         
            -
                # @api public
         
     | 
| 
      
 114 
     | 
    
         
            +
                # @!attribute [r] mappers
         
     | 
| 
      
 115 
     | 
    
         
            +
                #   @return [Hash] A hash with configured custom mappers
         
     | 
| 
       120 
116 
     | 
    
         
             
                attr_reader :mappers
         
     | 
| 
       121 
117 
     | 
    
         | 
| 
       122 
118 
     | 
    
         
             
                # @api private
         
     | 
    
        data/lib/rom/gateway.rb
    CHANGED
    
    | 
         @@ -5,49 +5,61 @@ require 'rom/transaction' 
     | 
|
| 
       5 
5 
     | 
    
         
             
            module ROM
         
     | 
| 
       6 
6 
     | 
    
         
             
              # Abstract gateway class
         
     | 
| 
       7 
7 
     | 
    
         
             
              #
         
     | 
| 
      
 8 
     | 
    
         
            +
              # Every adapter needs to inherit from this class and implement
         
     | 
| 
      
 9 
     | 
    
         
            +
              # required interface
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              # @abstract
         
     | 
| 
      
 12 
     | 
    
         
            +
              #
         
     | 
| 
       8 
13 
     | 
    
         
             
              # @api public
         
     | 
| 
       9 
14 
     | 
    
         
             
              class Gateway
         
     | 
| 
       10 
15 
     | 
    
         
             
                extend Dry::Core::ClassAttributes
         
     | 
| 
       11 
16 
     | 
    
         | 
| 
       12 
17 
     | 
    
         
             
                defines :adapter
         
     | 
| 
       13 
18 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                #  
     | 
| 
       15 
     | 
    
         
            -
                #
         
     | 
| 
       16 
     | 
    
         
            -
                # @return [Object] type varies depending on the gateway
         
     | 
| 
       17 
     | 
    
         
            -
                #
         
     | 
| 
       18 
     | 
    
         
            -
                # @api public
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @!attribute [r] connection
         
     | 
| 
      
 20 
     | 
    
         
            +
                #   @return [Object] The gateway's connection object (type varies across adapters)
         
     | 
| 
       19 
21 
     | 
    
         
             
                attr_reader :connection
         
     | 
| 
       20 
22 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                #  
     | 
| 
      
 23 
     | 
    
         
            +
                # Set up a gateway
         
     | 
| 
       22 
24 
     | 
    
         
             
                #
         
     | 
| 
       23 
25 
     | 
    
         
             
                # @overload setup(type, *args)
         
     | 
| 
       24 
26 
     | 
    
         
             
                #   Sets up a single-gateway given a gateway type.
         
     | 
| 
       25 
27 
     | 
    
         
             
                #   For custom gateways, create an instance and pass it directly.
         
     | 
| 
       26 
28 
     | 
    
         
             
                #
         
     | 
| 
       27 
     | 
    
         
            -
                #   @ 
     | 
| 
       28 
     | 
    
         
            -
                # 
     | 
| 
      
 29 
     | 
    
         
            +
                #   @example
         
     | 
| 
      
 30 
     | 
    
         
            +
                #     module SuperDB
         
     | 
| 
      
 31 
     | 
    
         
            +
                #       class Gateway < ROM::Gateway
         
     | 
| 
      
 32 
     | 
    
         
            +
                #         def initialize(options)
         
     | 
| 
      
 33 
     | 
    
         
            +
                #         end
         
     | 
| 
      
 34 
     | 
    
         
            +
                #       end
         
     | 
| 
      
 35 
     | 
    
         
            +
                #     end
         
     | 
| 
       29 
36 
     | 
    
         
             
                #
         
     | 
| 
       30 
     | 
    
         
            -
                #  
     | 
| 
       31 
     | 
    
         
            -
                #   @param [Gateway] gateway
         
     | 
| 
      
 37 
     | 
    
         
            +
                #     ROM.register_adapter(:super_db, SuperDB)
         
     | 
| 
       32 
38 
     | 
    
         
             
                #
         
     | 
| 
       33 
     | 
    
         
            -
                # 
     | 
| 
      
 39 
     | 
    
         
            +
                #     Gateway.setup(:super_db, some: 'options')
         
     | 
| 
      
 40 
     | 
    
         
            +
                #     # SuperDB::Gateway.new(some: 'options') is called
         
     | 
| 
      
 41 
     | 
    
         
            +
                #
         
     | 
| 
      
 42 
     | 
    
         
            +
                #   @param [Symbol] type Registered gateway identifier
         
     | 
| 
      
 43 
     | 
    
         
            +
                #   @param [Array] args Additional gateway options
         
     | 
| 
       34 
44 
     | 
    
         
             
                #
         
     | 
| 
       35 
     | 
    
         
            -
                # @ 
     | 
| 
       36 
     | 
    
         
            -
                #    
     | 
| 
       37 
     | 
    
         
            -
                # 
     | 
| 
       38 
     | 
    
         
            -
                # 
     | 
| 
      
 45 
     | 
    
         
            +
                # @overload setup(gateway)
         
     | 
| 
      
 46 
     | 
    
         
            +
                #   Set up a gateway instance
         
     | 
| 
      
 47 
     | 
    
         
            +
                #
         
     | 
| 
      
 48 
     | 
    
         
            +
                #   @example
         
     | 
| 
      
 49 
     | 
    
         
            +
                #     module SuperDB
         
     | 
| 
      
 50 
     | 
    
         
            +
                #       class Gateway < ROM::Gateway
         
     | 
| 
      
 51 
     | 
    
         
            +
                #         def initialize(options)
         
     | 
| 
      
 52 
     | 
    
         
            +
                #         end
         
     | 
| 
       39 
53 
     | 
    
         
             
                #       end
         
     | 
| 
       40 
54 
     | 
    
         
             
                #     end
         
     | 
| 
       41 
     | 
    
         
            -
                #   end
         
     | 
| 
       42 
55 
     | 
    
         
             
                #
         
     | 
| 
       43 
     | 
    
         
            -
                # 
     | 
| 
      
 56 
     | 
    
         
            +
                #     ROM.register_adapter(:super_db, SuperDB)
         
     | 
| 
      
 57 
     | 
    
         
            +
                #
         
     | 
| 
      
 58 
     | 
    
         
            +
                #     Gateway.setup(SuperDB::Gateway.new(some: 'options'))
         
     | 
| 
       44 
59 
     | 
    
         
             
                #
         
     | 
| 
       45 
     | 
    
         
            -
                #   Gateway 
     | 
| 
       46 
     | 
    
         
            -
                #   # SuperDB::Gateway.new(some: 'options') is called
         
     | 
| 
      
 60 
     | 
    
         
            +
                #   @param [Gateway] gateway
         
     | 
| 
       47 
61 
     | 
    
         
             
                #
         
     | 
| 
       48 
     | 
    
         
            -
                # 
     | 
| 
       49 
     | 
    
         
            -
                #   super_db = Gateway.setup(SuperDB::Gateway.new(some: 'options'))
         
     | 
| 
       50 
     | 
    
         
            -
                #   Gateway.setup(super_db)
         
     | 
| 
      
 62 
     | 
    
         
            +
                # @return [Gateway] a specific gateway subclass
         
     | 
| 
       51 
63 
     | 
    
         
             
                #
         
     | 
| 
       52 
64 
     | 
    
         
             
                # @api public
         
     | 
| 
       53 
65 
     | 
    
         
             
                def self.setup(gateway_or_scheme, *args)
         
     | 
| 
         @@ -76,7 +88,7 @@ module ROM 
     | 
|
| 
       76 
88 
     | 
    
         | 
| 
       77 
89 
     | 
    
         
             
                # Get gateway subclass for a specific adapter
         
     | 
| 
       78 
90 
     | 
    
         
             
                #
         
     | 
| 
       79 
     | 
    
         
            -
                # @param [Symbol] type  
     | 
| 
      
 91 
     | 
    
         
            +
                # @param [Symbol] type Adapter identifier
         
     | 
| 
       80 
92 
     | 
    
         
             
                #
         
     | 
| 
       81 
93 
     | 
    
         
             
                # @return [Class]
         
     | 
| 
       82 
94 
     | 
    
         
             
                #
         
     | 
| 
         @@ -109,6 +121,10 @@ module ROM 
     | 
|
| 
       109 
121 
     | 
    
         | 
| 
       110 
122 
     | 
    
         
             
                # A generic interface for setting up a logger
         
     | 
| 
       111 
123 
     | 
    
         
             
                #
         
     | 
| 
      
 124 
     | 
    
         
            +
                # This is not a required interface, it's a no-op by default
         
     | 
| 
      
 125 
     | 
    
         
            +
                #
         
     | 
| 
      
 126 
     | 
    
         
            +
                # @abstract
         
     | 
| 
      
 127 
     | 
    
         
            +
                #
         
     | 
| 
       112 
128 
     | 
    
         
             
                # @api public
         
     | 
| 
       113 
129 
     | 
    
         
             
                def use_logger(*)
         
     | 
| 
       114 
130 
     | 
    
         
             
                  # noop
         
     | 
| 
         @@ -116,6 +132,11 @@ module ROM 
     | 
|
| 
       116 
132 
     | 
    
         | 
| 
       117 
133 
     | 
    
         
             
                # A generic interface for returning default logger
         
     | 
| 
       118 
134 
     | 
    
         
             
                #
         
     | 
| 
      
 135 
     | 
    
         
            +
                # Adapters should implement this method as handling loggers is different
         
     | 
| 
      
 136 
     | 
    
         
            +
                # across adapters. This is a no-op by default and returns nil.
         
     | 
| 
      
 137 
     | 
    
         
            +
                #
         
     | 
| 
      
 138 
     | 
    
         
            +
                # @return [NilClass]
         
     | 
| 
      
 139 
     | 
    
         
            +
                #
         
     | 
| 
       119 
140 
     | 
    
         
             
                # @api public
         
     | 
| 
       120 
141 
     | 
    
         
             
                def logger
         
     | 
| 
       121 
142 
     | 
    
         
             
                  # noop
         
     | 
| 
         @@ -123,8 +144,10 @@ module ROM 
     | 
|
| 
       123 
144 
     | 
    
         | 
| 
       124 
145 
     | 
    
         
             
                # Extension hook for adding gateway-specific behavior to a command class
         
     | 
| 
       125 
146 
     | 
    
         
             
                #
         
     | 
| 
       126 
     | 
    
         
            -
                #  
     | 
| 
       127 
     | 
    
         
            -
                # 
     | 
| 
      
 147 
     | 
    
         
            +
                # This simply returns back the class by default
         
     | 
| 
      
 148 
     | 
    
         
            +
                #
         
     | 
| 
      
 149 
     | 
    
         
            +
                # @param [Class] klass The command class
         
     | 
| 
      
 150 
     | 
    
         
            +
                # @param [Object] _dataset The dataset that will be used with this command class
         
     | 
| 
       128 
151 
     | 
    
         
             
                #
         
     | 
| 
       129 
152 
     | 
    
         
             
                # @return [Class]
         
     | 
| 
       130 
153 
     | 
    
         
             
                #
         
     | 
| 
         @@ -137,7 +160,7 @@ module ROM 
     | 
|
| 
       137 
160 
     | 
    
         
             
                #
         
     | 
| 
       138 
161 
     | 
    
         
             
                # Every gateway that supports schema inference should implement this method
         
     | 
| 
       139 
162 
     | 
    
         
             
                #
         
     | 
| 
       140 
     | 
    
         
            -
                # @return [Array] array with  
     | 
| 
      
 163 
     | 
    
         
            +
                # @return [Array] An array with dataset names
         
     | 
| 
       141 
164 
     | 
    
         
             
                #
         
     | 
| 
       142 
165 
     | 
    
         
             
                # @api private
         
     | 
| 
       143 
166 
     | 
    
         
             
                def schema
         
     | 
| 
         @@ -163,6 +186,8 @@ module ROM 
     | 
|
| 
       163 
186 
     | 
    
         
             
                  transaction_runner(opts).run(opts, &block)
         
     | 
| 
       164 
187 
     | 
    
         
             
                end
         
     | 
| 
       165 
188 
     | 
    
         | 
| 
      
 189 
     | 
    
         
            +
                private
         
     | 
| 
      
 190 
     | 
    
         
            +
             
     | 
| 
       166 
191 
     | 
    
         
             
                # @api private
         
     | 
| 
       167 
192 
     | 
    
         
             
                def transaction_runner(_)
         
     | 
| 
       168 
193 
     | 
    
         
             
                  Transaction::NoOp
         
     | 
    
        data/lib/rom/relation.rb
    CHANGED
    
    | 
         @@ -18,18 +18,23 @@ module ROM 
     | 
|
| 
       18 
18 
     | 
    
         
             
              # Base relation class
         
     | 
| 
       19 
19 
     | 
    
         
             
              #
         
     | 
| 
       20 
20 
     | 
    
         
             
              # Relation is a proxy for the dataset object provided by the gateway. It
         
     | 
| 
       21 
     | 
    
         
            -
              #  
     | 
| 
      
 21 
     | 
    
         
            +
              # can forward methods to the dataset, which is why the "native" interface of
         
     | 
| 
       22 
22 
     | 
    
         
             
              # the underlying gateway is available in the relation. This interface,
         
     | 
| 
       23 
23 
     | 
    
         
             
              # however, is considered private and should not be used outside of the
         
     | 
| 
       24 
24 
     | 
    
         
             
              # relation instance.
         
     | 
| 
       25 
25 
     | 
    
         
             
              #
         
     | 
| 
       26 
     | 
    
         
            -
              #  
     | 
| 
       27 
     | 
    
         
            -
              #  
     | 
| 
       28 
     | 
    
         
            -
              # 
     | 
| 
       29 
     | 
    
         
            -
              #  
     | 
| 
      
 26 
     | 
    
         
            +
              # Individual adapters sets up their relation classes and provide different APIs
         
     | 
| 
      
 27 
     | 
    
         
            +
              # depending on their persistence backend.
         
     | 
| 
      
 28 
     | 
    
         
            +
              #
         
     | 
| 
      
 29 
     | 
    
         
            +
              # Vanilla Relation class doesn't have APIs that are specific to ROM container setup.
         
     | 
| 
      
 30 
     | 
    
         
            +
              # When adapter Relation class inherits from this class, these APIs are added automatically,
         
     | 
| 
      
 31 
     | 
    
         
            +
              # so that they can be registered within a container.
         
     | 
| 
      
 32 
     | 
    
         
            +
              #
         
     | 
| 
      
 33 
     | 
    
         
            +
              # @see ROM::Relation::ClassInterface
         
     | 
| 
       30 
34 
     | 
    
         
             
              #
         
     | 
| 
       31 
35 
     | 
    
         
             
              # @api public
         
     | 
| 
       32 
36 
     | 
    
         
             
              class Relation
         
     | 
| 
      
 37 
     | 
    
         
            +
                # Default no-op output schema which is called in `Relation#each`
         
     | 
| 
       33 
38 
     | 
    
         
             
                NOOP_OUTPUT_SCHEMA = -> tuple { tuple }.freeze
         
     | 
| 
       34 
39 
     | 
    
         | 
| 
       35 
40 
     | 
    
         
             
                extend Initializer
         
     | 
| 
         @@ -71,6 +76,15 @@ module ROM 
     | 
|
| 
       71 
76 
     | 
    
         | 
| 
       72 
77 
     | 
    
         
             
                # Return schema attribute
         
     | 
| 
       73 
78 
     | 
    
         
             
                #
         
     | 
| 
      
 79 
     | 
    
         
            +
                # @example accessing canonical attribute
         
     | 
| 
      
 80 
     | 
    
         
            +
                #   users[:id]
         
     | 
| 
      
 81 
     | 
    
         
            +
                #   # => #<ROM::SQL::Attribute[Integer] primary_key=true name=:id source=ROM::Relation::Name(users)>
         
     | 
| 
      
 82 
     | 
    
         
            +
                #
         
     | 
| 
      
 83 
     | 
    
         
            +
                # @example accessing joined attribute
         
     | 
| 
      
 84 
     | 
    
         
            +
                #   tasks_with_users = tasks.join(users).select_append(tasks[:title])
         
     | 
| 
      
 85 
     | 
    
         
            +
                #   tasks_with_users[:title, :tasks]
         
     | 
| 
      
 86 
     | 
    
         
            +
                #   # => #<ROM::SQL::Attribute[String] primary_key=false name=:title source=ROM::Relation::Name(tasks)>
         
     | 
| 
      
 87 
     | 
    
         
            +
                #
         
     | 
| 
       74 
88 
     | 
    
         
             
                # @return [Schema::Attribute]
         
     | 
| 
       75 
89 
     | 
    
         
             
                #
         
     | 
| 
       76 
90 
     | 
    
         
             
                # @api public
         
     | 
| 
         @@ -80,7 +94,10 @@ module ROM 
     | 
|
| 
       80 
94 
     | 
    
         | 
| 
       81 
95 
     | 
    
         
             
                # Yields relation tuples
         
     | 
| 
       82 
96 
     | 
    
         
             
                #
         
     | 
| 
      
 97 
     | 
    
         
            +
                # Every tuple is processed through Relation#output_schema, it's a no-op by default
         
     | 
| 
      
 98 
     | 
    
         
            +
                #
         
     | 
| 
       83 
99 
     | 
    
         
             
                # @yield [Hash]
         
     | 
| 
      
 100 
     | 
    
         
            +
                #
         
     | 
| 
       84 
101 
     | 
    
         
             
                # @return [Enumerator] if block is not provided
         
     | 
| 
       85 
102 
     | 
    
         
             
                #
         
     | 
| 
       86 
103 
     | 
    
         
             
                # @api public
         
     | 
| 
         @@ -91,7 +108,7 @@ module ROM 
     | 
|
| 
       91 
108 
     | 
    
         | 
| 
       92 
109 
     | 
    
         
             
                # Composes with other relations
         
     | 
| 
       93 
110 
     | 
    
         
             
                #
         
     | 
| 
       94 
     | 
    
         
            -
                # @param  
     | 
| 
      
 111 
     | 
    
         
            +
                # @param [Array<Relation>] others The other relation(s) to compose with
         
     | 
| 
       95 
112 
     | 
    
         
             
                #
         
     | 
| 
       96 
113 
     | 
    
         
             
                # @return [Relation::Graph]
         
     | 
| 
       97 
114 
     | 
    
         
             
                #
         
     | 
| 
         @@ -147,6 +164,18 @@ module ROM 
     | 
|
| 
       147 
164 
     | 
    
         | 
| 
       148 
165 
     | 
    
         
             
                # Return a new relation with provided dataset and additional options
         
     | 
| 
       149 
166 
     | 
    
         
             
                #
         
     | 
| 
      
 167 
     | 
    
         
            +
                # Use this method whenever you need to use dataset API to get a new dataset
         
     | 
| 
      
 168 
     | 
    
         
            +
                # and you want to return a relation back. Typically relation API should be
         
     | 
| 
      
 169 
     | 
    
         
            +
                # enough though. If you find yourself using this method, it might be worth
         
     | 
| 
      
 170 
     | 
    
         
            +
                # to consider reporting an issue that some dataset functionality is not available
         
     | 
| 
      
 171 
     | 
    
         
            +
                # through relation API.
         
     | 
| 
      
 172 
     | 
    
         
            +
                #
         
     | 
| 
      
 173 
     | 
    
         
            +
                # @example with a new dataset
         
     | 
| 
      
 174 
     | 
    
         
            +
                #   users.new(users.dataset.some_method)
         
     | 
| 
      
 175 
     | 
    
         
            +
                #
         
     | 
| 
      
 176 
     | 
    
         
            +
                # @example with a new dataset and options
         
     | 
| 
      
 177 
     | 
    
         
            +
                #   users.new(users.dataset.some_method, other: 'options')
         
     | 
| 
      
 178 
     | 
    
         
            +
                #
         
     | 
| 
       150 
179 
     | 
    
         
             
                # @param [Object] dataset
         
     | 
| 
       151 
180 
     | 
    
         
             
                # @param [Hash] new_opts Additional options
         
     | 
| 
       152 
181 
     | 
    
         
             
                #
         
     | 
| 
         @@ -157,6 +186,9 @@ module ROM 
     | 
|
| 
       157 
186 
     | 
    
         | 
| 
       158 
187 
     | 
    
         
             
                # Returns a new instance with the same dataset but new options
         
     | 
| 
       159 
188 
     | 
    
         
             
                #
         
     | 
| 
      
 189 
     | 
    
         
            +
                # @example
         
     | 
| 
      
 190 
     | 
    
         
            +
                #   users.with(output_schema: -> tuple { .. })
         
     | 
| 
      
 191 
     | 
    
         
            +
                #
         
     | 
| 
       160 
192 
     | 
    
         
             
                # @param new_options [Hash]
         
     | 
| 
       161 
193 
     | 
    
         
             
                #
         
     | 
| 
       162 
194 
     | 
    
         
             
                # @return [Relation]
         
     | 
| 
         @@ -168,6 +200,8 @@ module ROM 
     | 
|
| 
       168 
200 
     | 
    
         | 
| 
       169 
201 
     | 
    
         
             
                # Return all registered relation schemas
         
     | 
| 
       170 
202 
     | 
    
         
             
                #
         
     | 
| 
      
 203 
     | 
    
         
            +
                # This holds all schemas defined via `view` DSL
         
     | 
| 
      
 204 
     | 
    
         
            +
                #
         
     | 
| 
       171 
205 
     | 
    
         
             
                # @return [Hash<Symbol=>Schema>]
         
     | 
| 
       172 
206 
     | 
    
         
             
                #
         
     | 
| 
       173 
207 
     | 
    
         
             
                # @api public
         
     | 
| 
         @@ -186,6 +220,10 @@ module ROM 
     | 
|
| 
       186 
220 
     | 
    
         | 
| 
       187 
221 
     | 
    
         
             
                private
         
     | 
| 
       188 
222 
     | 
    
         | 
| 
      
 223 
     | 
    
         
            +
                # Hook used by `Pipeline` to get the class that should be used for composition
         
     | 
| 
      
 224 
     | 
    
         
            +
                #
         
     | 
| 
      
 225 
     | 
    
         
            +
                # @return [Class]
         
     | 
| 
      
 226 
     | 
    
         
            +
                #
         
     | 
| 
       189 
227 
     | 
    
         
             
                # @api private
         
     | 
| 
       190 
228 
     | 
    
         
             
                def composite_class
         
     | 
| 
       191 
229 
     | 
    
         
             
                  Relation::Composite
         
     | 
    
        data/lib/rom/version.rb
    CHANGED
    
    
| 
         @@ -94,7 +94,7 @@ RSpec.describe ROM::Commands::Create[:memory], 'before/after hooks' do 
     | 
|
| 
       94 
94 
     | 
    
         
             
                end
         
     | 
| 
       95 
95 
     | 
    
         
             
              end
         
     | 
| 
       96 
96 
     | 
    
         | 
| 
       97 
     | 
    
         
            -
              context 'with curried  
     | 
| 
      
 97 
     | 
    
         
            +
              context 'with one curried arg' do
         
     | 
| 
       98 
98 
     | 
    
         
             
                subject(:command) do
         
     | 
| 
       99 
99 
     | 
    
         
             
                  Class.new(ROM::Commands::Create[:memory]) do
         
     | 
| 
       100 
100 
     | 
    
         
             
                    result :many
         
     | 
| 
         @@ -142,6 +142,54 @@ RSpec.describe ROM::Commands::Create[:memory], 'before/after hooks' do 
     | 
|
| 
       142 
142 
     | 
    
         
             
                end
         
     | 
| 
       143 
143 
     | 
    
         
             
              end
         
     | 
| 
       144 
144 
     | 
    
         | 
| 
      
 145 
     | 
    
         
            +
              context 'with 2 curried args' do
         
     | 
| 
      
 146 
     | 
    
         
            +
                subject(:command) do
         
     | 
| 
      
 147 
     | 
    
         
            +
                  Class.new(ROM::Commands::Create[:memory]) do
         
     | 
| 
      
 148 
     | 
    
         
            +
                    result :many
         
     | 
| 
      
 149 
     | 
    
         
            +
                    before :prepare
         
     | 
| 
      
 150 
     | 
    
         
            +
                    after :finalize
         
     | 
| 
      
 151 
     | 
    
         
            +
             
     | 
| 
      
 152 
     | 
    
         
            +
                    def execute(tuples)
         
     | 
| 
      
 153 
     | 
    
         
            +
                      input = tuples.map.with_index { |tuple, idx| tuple.merge(id: idx + 1) }
         
     | 
| 
      
 154 
     | 
    
         
            +
                      relation.insert(input)
         
     | 
| 
      
 155 
     | 
    
         
            +
                      input
         
     | 
| 
      
 156 
     | 
    
         
            +
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
                    def prepare(tuples, name)
         
     | 
| 
      
 159 
     | 
    
         
            +
                      tuples.map.with_index { |tuple, idx| tuple.merge(name: "#{name} #{idx + 1}") }
         
     | 
| 
      
 160 
     | 
    
         
            +
                    end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
                    def finalize(tuples, *)
         
     | 
| 
      
 163 
     | 
    
         
            +
                      tuples.map { |tuple| tuple.merge(finalized: true) }
         
     | 
| 
      
 164 
     | 
    
         
            +
                    end
         
     | 
| 
      
 165 
     | 
    
         
            +
                  end.build(relation)
         
     | 
| 
      
 166 
     | 
    
         
            +
                end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                let(:tuples) do
         
     | 
| 
      
 169 
     | 
    
         
            +
                  [{ email: 'user-1@test.com' }, { email: 'user-2@test.com' }]
         
     | 
| 
      
 170 
     | 
    
         
            +
                end
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                let(:relation) do
         
     | 
| 
      
 173 
     | 
    
         
            +
                  spy(:relation)
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                it 'applies before/after hooks' do
         
     | 
| 
      
 177 
     | 
    
         
            +
                  insert_tuples = [
         
     | 
| 
      
 178 
     | 
    
         
            +
                    { id: 1, email: 'user-1@test.com', name: 'User 1' },
         
     | 
| 
      
 179 
     | 
    
         
            +
                    { id: 2, email: 'user-2@test.com', name: 'User 2' }
         
     | 
| 
      
 180 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 181 
     | 
    
         
            +
             
     | 
| 
      
 182 
     | 
    
         
            +
                  result = [
         
     | 
| 
      
 183 
     | 
    
         
            +
                    { id: 1, email: 'user-1@test.com', name: 'User 1', finalized: true },
         
     | 
| 
      
 184 
     | 
    
         
            +
                    { id: 2, email: 'user-2@test.com', name: 'User 2', finalized: true }
         
     | 
| 
      
 185 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
                  expect(command.with(tuples, 'User').call).to eql(result)
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                  expect(relation).to have_received(:insert).with(insert_tuples)
         
     | 
| 
      
 190 
     | 
    
         
            +
                end
         
     | 
| 
      
 191 
     | 
    
         
            +
              end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
       145 
193 
     | 
    
         
             
              context 'with pre-set opts' do
         
     | 
| 
       146 
194 
     | 
    
         
             
                subject(:command) do
         
     | 
| 
       147 
195 
     | 
    
         
             
                  Class.new(ROM::Commands::Create[:memory]) do
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: rom
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 3.0.0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 3.0.0.rc2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Piotr Solnica
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2017-01- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2017-01-27 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: concurrent-ruby
         
     |