service_actor 3.1.3 → 3.2.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/README.md +90 -64
- data/lib/service_actor/base.rb +13 -13
- data/lib/service_actor/collectionable.rb +1 -1
- data/lib/service_actor/conditionable.rb +1 -1
- data/lib/service_actor/core.rb +6 -6
- data/lib/service_actor/nil_checkable.rb +3 -3
- data/lib/service_actor/playable.rb +19 -10
- data/lib/service_actor/result.rb +24 -1
- data/lib/service_actor/type_checkable.rb +3 -3
- data/lib/service_actor/version.rb +1 -1
- data/lib/service_actor.rb +1 -1
- metadata +11 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 8bde0ceb526951927f7349b5bd80dc2d6ca036e40e7dbc3ca98bc027f47fbd4c
         | 
| 4 | 
            +
              data.tar.gz: cd90e8762fe61eccd643fcdb318ebb27b79a561dbc8075ae4e2c802734ace9f7
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2cddbccf7794088dc4a25b011cdb1155d0b6e855abd4a83630402ec90d4fe2f6c4c7fa4a0935ddca7faee58e49b2ff3d1f9f99b430c76dcc2990452d06d16ded
         | 
| 7 | 
            +
              data.tar.gz: 81444f049effd685780bd4904c3513c7d7adf220c2ecf4ca6a3bf18e077d1b207786f6b85eeb02597e23700bf2a661c3a83f2c4602333bf85c6adf7e810652ef
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            #  | 
| 1 | 
            +
            # ServiceActor
         | 
| 2 2 |  | 
| 3 3 | 
             
            
         | 
| 4 4 |  | 
| @@ -21,31 +21,37 @@ and controllers thin. | |
| 21 21 | 
             
              - [Fail](#fail)
         | 
| 22 22 | 
             
            - [Play actors in a sequence](#play-actors-in-a-sequence)
         | 
| 23 23 | 
             
              - [Rollback](#rollback)
         | 
| 24 | 
            -
              - [ | 
| 24 | 
            +
              - [Inline actors](#inline-actors)
         | 
| 25 25 | 
             
              - [Play conditions](#play-conditions)
         | 
| 26 26 | 
             
            - [Testing](#testing)
         | 
| 27 27 | 
             
            - [Build your own actor](#build-your-own-actor)
         | 
| 28 28 | 
             
            - [Influences](#influences)
         | 
| 29 29 | 
             
            - [Thanks](#thanks)
         | 
| 30 | 
            -
            - [Development](#development)
         | 
| 31 30 | 
             
            - [Contributing](#contributing)
         | 
| 32 31 | 
             
            - [License](#contributing)
         | 
| 33 32 |  | 
| 34 33 | 
             
            ## Installation
         | 
| 35 34 |  | 
| 36 | 
            -
            Add  | 
| 35 | 
            +
            Add the gem to your application’s Gemfile by executing:
         | 
| 37 36 |  | 
| 38 | 
            -
            ``` | 
| 39 | 
            -
             | 
| 40 | 
            -
            gem 'service_actor'
         | 
| 37 | 
            +
            ```sh
         | 
| 38 | 
            +
            bundle add service_actor
         | 
| 41 39 | 
             
            ```
         | 
| 42 40 |  | 
| 43 | 
            -
             | 
| 41 | 
            +
            ### Extensions
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            For **Rails generators**, you can use the
         | 
| 44 44 | 
             
            [service_actor-rails](https://github.com/sunny/actor-rails) gem:
         | 
| 45 45 |  | 
| 46 | 
            -
            ``` | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 46 | 
            +
            ```sh
         | 
| 47 | 
            +
            bundle add service_actor-rails
         | 
| 48 | 
            +
            ```
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            For **TTY prompts**, you can use the
         | 
| 51 | 
            +
            [service_actor-promptable](https://github.com/pboling/service_actor-promptable) gem:
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            ```sh
         | 
| 54 | 
            +
            bundle add service_actor-promptable
         | 
| 49 55 | 
             
            ```
         | 
| 50 56 |  | 
| 51 57 | 
             
            ## Usage
         | 
| @@ -69,9 +75,10 @@ Trigger them in your application with `.call`: | |
| 69 75 | 
             
            SendNotification.call # => <ServiceActor::Result…>
         | 
| 70 76 | 
             
            ```
         | 
| 71 77 |  | 
| 72 | 
            -
            When called,  | 
| 73 | 
            -
            actors to accept and return multiple arguments. Let | 
| 74 | 
            -
            and then we | 
| 78 | 
            +
            When called, an actor returns a result. Reading and writing to this result allows
         | 
| 79 | 
            +
            actors to accept and return multiple arguments. Let’s find out how to do that
         | 
| 80 | 
            +
            and then we’ll see how to
         | 
| 81 | 
            +
            [chain multiple actors togethor](#play-actors-in-a-sequence).
         | 
| 75 82 |  | 
| 76 83 | 
             
            ### Inputs
         | 
| 77 84 |  | 
| @@ -111,8 +118,19 @@ end | |
| 111 118 | 
             
            The result you get from calling an actor will include the outputs you set:
         | 
| 112 119 |  | 
| 113 120 | 
             
            ```rb
         | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 121 | 
            +
            actor = BuildGreeting.call
         | 
| 122 | 
            +
            actor.greeting # => "Have a wonderful day!"
         | 
| 123 | 
            +
            ```
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            For every output there is also a boolean method ending with `?` to test its
         | 
| 126 | 
            +
            presence:
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            ```rb
         | 
| 129 | 
            +
            if actor.greeting?
         | 
| 130 | 
            +
              puts "Greetings is truthy"
         | 
| 131 | 
            +
            else
         | 
| 132 | 
            +
              puts "Greetings is falsey"
         | 
| 133 | 
            +
            end
         | 
| 116 134 | 
             
            ```
         | 
| 117 135 |  | 
| 118 136 | 
             
            ### Defaults
         | 
| @@ -136,14 +154,14 @@ end | |
| 136 154 | 
             
            This lets you call the actor without specifying those keys:
         | 
| 137 155 |  | 
| 138 156 | 
             
            ```rb
         | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 157 | 
            +
            actor = BuildGreeting.call(name: "Jim")
         | 
| 158 | 
            +
            actor.greeting # => "Have a wonderful week Jim!"
         | 
| 141 159 | 
             
            ```
         | 
| 142 160 |  | 
| 143 161 | 
             
            If an input does not have a default, it will raise a error:
         | 
| 144 162 |  | 
| 145 163 | 
             
            ```rb
         | 
| 146 | 
            -
             | 
| 164 | 
            +
            BuildGreeting.call
         | 
| 147 165 | 
             
            => ServiceActor::ArgumentError: Input name on BuildGreeting is missing.
         | 
| 148 166 | 
             
            ```
         | 
| 149 167 |  | 
| @@ -168,7 +186,7 @@ You can also add custom conditions with the name of your choice by using `must`: | |
| 168 186 | 
             
            class UpdateAdminUser < Actor
         | 
| 169 187 | 
             
              input :user,
         | 
| 170 188 | 
             
                    must: {
         | 
| 171 | 
            -
                      be_an_admin: -> | 
| 189 | 
            +
                      be_an_admin: -> user { user.admin? }
         | 
| 172 190 | 
             
                    }
         | 
| 173 191 |  | 
| 174 192 | 
             
              # …
         | 
| @@ -207,7 +225,7 @@ class UpdateUser < Actor | |
| 207 225 | 
             
            end
         | 
| 208 226 | 
             
            ```
         | 
| 209 227 |  | 
| 210 | 
            -
            You may also use strings instead of constants, such as `type:  | 
| 228 | 
            +
            You may also use strings instead of constants, such as `type: "User"`.
         | 
| 211 229 |  | 
| 212 230 | 
             
            When using a type condition, `allow_nil` defaults to `false`.
         | 
| 213 231 |  | 
| @@ -242,11 +260,11 @@ For example in a Rails controller: | |
| 242 260 | 
             
            # app/controllers/users_controller.rb
         | 
| 243 261 | 
             
            class UsersController < ApplicationController
         | 
| 244 262 | 
             
              def create
         | 
| 245 | 
            -
                 | 
| 246 | 
            -
                if  | 
| 247 | 
            -
                  redirect_to  | 
| 263 | 
            +
                actor = UpdateUser.result(user: user, attributes: user_attributes)
         | 
| 264 | 
            +
                if actor.success?
         | 
| 265 | 
            +
                  redirect_to actor.user
         | 
| 248 266 | 
             
                else
         | 
| 249 | 
            -
                  render :new, notice:  | 
| 267 | 
            +
                  render :new, notice: actor.error
         | 
| 250 268 | 
             
                end
         | 
| 251 269 | 
             
              end
         | 
| 252 270 | 
             
            end
         | 
| @@ -263,7 +281,7 @@ actor can use `play` to call other actors: | |
| 263 281 | 
             
            ```rb
         | 
| 264 282 | 
             
            class PlaceOrder < Actor
         | 
| 265 283 | 
             
              play CreateOrder,
         | 
| 266 | 
            -
                    | 
| 284 | 
            +
                   PayOrder,
         | 
| 267 285 | 
             
                   SendOrderConfirmation,
         | 
| 268 286 | 
             
                   NotifyAdmins
         | 
| 269 287 | 
             
            end
         | 
| @@ -299,26 +317,51 @@ Rollback is only called on the _previous_ actors in `play` and is not called on | |
| 299 317 | 
             
            the failing actor itself. Actors should be kept to a single purpose and not have
         | 
| 300 318 | 
             
            anything to clean up if they call `fail!`.
         | 
| 301 319 |  | 
| 302 | 
            -
            ###  | 
| 320 | 
            +
            ### Inline actors
         | 
| 303 321 |  | 
| 304 | 
            -
             | 
| 305 | 
            -
            the shared result | 
| 322 | 
            +
            For small work or preparing the result set for the next actors, you can create
         | 
| 323 | 
            +
            inline actors by using lambdas. Each lambda has access to the shared result. For
         | 
| 324 | 
            +
            example:
         | 
| 306 325 |  | 
| 307 326 | 
             
            ```rb
         | 
| 308 | 
            -
            class  | 
| 309 | 
            -
               | 
| 327 | 
            +
            class PayOrder < Actor
         | 
| 328 | 
            +
              input :order
         | 
| 329 | 
            +
             | 
| 330 | 
            +
              play -> actor { actor.order.currency ||= "EUR" },
         | 
| 310 331 | 
             
                   CreatePayment,
         | 
| 311 | 
            -
                    | 
| 312 | 
            -
                    | 
| 332 | 
            +
                   UpdateOrderBalance,
         | 
| 333 | 
            +
                   -> actor { Logger.info("Order #{actor.order.id} paid") }
         | 
| 313 334 | 
             
            end
         | 
| 314 335 | 
             
            ```
         | 
| 315 336 |  | 
| 316 | 
            -
             | 
| 317 | 
            -
            result for the next actors. If you want to do more work before, after or around
         | 
| 318 | 
            -
            the whole `play`, you can also override the `call` method. For example:
         | 
| 337 | 
            +
            You can also call instance methods. For example:
         | 
| 319 338 |  | 
| 320 339 | 
             
            ```rb
         | 
| 321 | 
            -
            class  | 
| 340 | 
            +
            class PayOrder < Actor
         | 
| 341 | 
            +
              input :order
         | 
| 342 | 
            +
             | 
| 343 | 
            +
              play :assign_default_currency,
         | 
| 344 | 
            +
                   CreatePayment,
         | 
| 345 | 
            +
                   UpdateOrderBalance,
         | 
| 346 | 
            +
                   :log_payment
         | 
| 347 | 
            +
             | 
| 348 | 
            +
              private
         | 
| 349 | 
            +
             | 
| 350 | 
            +
              def assign_default_currency
         | 
| 351 | 
            +
                order.currency ||= "EUR"
         | 
| 352 | 
            +
              end
         | 
| 353 | 
            +
             | 
| 354 | 
            +
              def log_payment
         | 
| 355 | 
            +
                Logger.info("Order #{order.id} paid")
         | 
| 356 | 
            +
              end
         | 
| 357 | 
            +
            end
         | 
| 358 | 
            +
            ```
         | 
| 359 | 
            +
             | 
| 360 | 
            +
            If you want to do work around the whole actor, you can also override the `call`
         | 
| 361 | 
            +
            method. For example:
         | 
| 362 | 
            +
             | 
| 363 | 
            +
            ```rb
         | 
| 364 | 
            +
            class PayOrder < Actor
         | 
| 322 365 | 
             
              # …
         | 
| 323 366 |  | 
| 324 367 | 
             
              def call
         | 
| @@ -337,12 +380,10 @@ Actors in a play can be called conditionally: | |
| 337 380 | 
             
            class PlaceOrder < Actor
         | 
| 338 381 | 
             
              play CreateOrder,
         | 
| 339 382 | 
             
                   Pay
         | 
| 340 | 
            -
              play NotifyAdmins, if: -> | 
| 383 | 
            +
              play NotifyAdmins, if: -> actor { actor.order.amount > 42 }
         | 
| 341 384 | 
             
            end
         | 
| 342 385 | 
             
            ```
         | 
| 343 386 |  | 
| 344 | 
            -
            You can use this to trigger an early success.
         | 
| 345 | 
            -
             | 
| 346 387 | 
             
            ### Fail on argument error
         | 
| 347 388 |  | 
| 348 389 | 
             
            By default, errors on inputs will raise an error, even when using `.result`
         | 
| @@ -392,7 +433,7 @@ Some key differences make Actor unique: | |
| 392 433 |  | 
| 393 434 | 
             
            - Does not [hide errors when an actor fails inside another
         | 
| 394 435 | 
             
              actor](https://github.com/collectiveidea/interactor/issues/170).
         | 
| 395 | 
            -
            - Requires you to document  | 
| 436 | 
            +
            - Requires you to document arguments with `input` and `output`.
         | 
| 396 437 | 
             
            - Defaults to raising errors on failures: actor uses `call` and `result`
         | 
| 397 438 | 
             
              instead of `call!` and `call`. This way, the _default_ is to raise an error
         | 
| 398 439 | 
             
              and failures are not hidden away because you forgot to use `!`.
         | 
| @@ -401,7 +442,8 @@ Some key differences make Actor unique: | |
| 401 442 | 
             
              `context.foo = `, `fail!` vs `context.fail!`.
         | 
| 402 443 | 
             
            - Shorter setup syntax: inherit from `< Actor` vs having to `include Interactor`
         | 
| 403 444 | 
             
              and `include Interactor::Organizer`.
         | 
| 404 | 
            -
            - Organizers allow lambdas, being called multiple times, | 
| 445 | 
            +
            - Organizers allow lambdas, instance methods, being called multiple times,
         | 
| 446 | 
            +
              and having conditions.
         | 
| 405 447 | 
             
            - Allows early success with conditions inside organizers.
         | 
| 406 448 | 
             
            - No `before`, `after` and `around` hooks, prefer using `play` with lambdas or
         | 
| 407 449 | 
             
              overriding `call`.
         | 
| @@ -414,33 +456,17 @@ migration. | |
| 414 456 | 
             
            Thank you to @nicoolas25, @AnneSottise & @williampollet for the early thoughts
         | 
| 415 457 | 
             
            and feedback on this gem.
         | 
| 416 458 |  | 
| 417 | 
            -
             | 
| 418 | 
            -
             | 
| 419 | 
            -
            ## Development
         | 
| 459 | 
            +
            Thank you to the wonderful
         | 
| 460 | 
            +
            [contributors](https://github.com/sunny/actor/graphs/contributors).
         | 
| 420 461 |  | 
| 421 | 
            -
             | 
| 422 | 
            -
            `bin/rake` to run the tests and linting. You can also run `bin/console` for an
         | 
| 423 | 
            -
            interactive prompt.
         | 
| 424 | 
            -
             | 
| 425 | 
            -
            To release a new version, update the version number in `version.rb`, and in the
         | 
| 426 | 
            -
            `CHANGELOG.md`. Update the `README.md` if there are missing segments, make sure
         | 
| 427 | 
            -
            tests and linting are pristine by calling `bundle && bin/rake`, then create a
         | 
| 428 | 
            -
            commit for this version.
         | 
| 429 | 
            -
             | 
| 430 | 
            -
            You can then run `rake release`, which will assign a git tag, push using git,
         | 
| 431 | 
            -
            and push the gem to [rubygems.org](https://rubygems.org).
         | 
| 462 | 
            +
            Photo by [Lloyd Dirks](https://unsplash.com/photos/4SLz_RCk6kQ).
         | 
| 432 463 |  | 
| 433 464 | 
             
            ## Contributing
         | 
| 434 465 |  | 
| 435 | 
            -
             | 
| 436 | 
            -
            [ | 
| 437 | 
            -
             | 
| 438 | 
            -
            This project is intended to be a safe, welcoming space for collaboration, and
         | 
| 439 | 
            -
            everyone interacting in the project’s codebase and issue tracker is expected to
         | 
| 440 | 
            -
            adhere to the [Contributor Covenant code of
         | 
| 441 | 
            -
            conduct](https://github.com/sunny/actor/blob/main/CODE_OF_CONDUCT.md).
         | 
| 466 | 
            +
            See
         | 
| 467 | 
            +
            [CONTRIBUTING.md](https://github.com/sunny/actor/blob/main/CONTRIBUTING.md).
         | 
| 442 468 |  | 
| 443 469 | 
             
            ## License
         | 
| 444 470 |  | 
| 445 471 | 
             
            The gem is available as open source under the terms of the
         | 
| 446 | 
            -
            [MIT License](https:// | 
| 472 | 
            +
            [MIT License](https://choosealicense.com/licenses/mit/).
         | 
    
        data/lib/service_actor/base.rb
    CHANGED
    
    | @@ -1,23 +1,23 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 3 | 
             
            # Exceptions
         | 
| 4 | 
            -
            require  | 
| 5 | 
            -
            require  | 
| 6 | 
            -
            require  | 
| 4 | 
            +
            require "service_actor/error"
         | 
| 5 | 
            +
            require "service_actor/failure"
         | 
| 6 | 
            +
            require "service_actor/argument_error"
         | 
| 7 7 |  | 
| 8 8 | 
             
            # Core
         | 
| 9 | 
            -
            require  | 
| 10 | 
            -
            require  | 
| 11 | 
            -
            require  | 
| 12 | 
            -
            require  | 
| 9 | 
            +
            require "service_actor/core"
         | 
| 10 | 
            +
            require "service_actor/attributable"
         | 
| 11 | 
            +
            require "service_actor/playable"
         | 
| 12 | 
            +
            require "service_actor/result"
         | 
| 13 13 |  | 
| 14 14 | 
             
            # Concerns
         | 
| 15 | 
            -
            require  | 
| 16 | 
            -
            require  | 
| 17 | 
            -
            require  | 
| 18 | 
            -
            require  | 
| 19 | 
            -
            require  | 
| 20 | 
            -
            require  | 
| 15 | 
            +
            require "service_actor/type_checkable"
         | 
| 16 | 
            +
            require "service_actor/nil_checkable"
         | 
| 17 | 
            +
            require "service_actor/conditionable"
         | 
| 18 | 
            +
            require "service_actor/defaultable"
         | 
| 19 | 
            +
            require "service_actor/collectionable"
         | 
| 20 | 
            +
            require "service_actor/failable"
         | 
| 21 21 |  | 
| 22 22 | 
             
            module ServiceActor
         | 
| 23 23 | 
             
              module Base
         | 
    
        data/lib/service_actor/core.rb
    CHANGED
    
    | @@ -9,9 +9,9 @@ module ServiceActor | |
| 9 9 | 
             
                module ClassMethods
         | 
| 10 10 | 
             
                  # Call an actor with a given result. Returns the result.
         | 
| 11 11 | 
             
                  #
         | 
| 12 | 
            -
                  #   CreateUser.call(name:  | 
| 13 | 
            -
                  def call( | 
| 14 | 
            -
                    result = Result.to_result( | 
| 12 | 
            +
                  #   CreateUser.call(name: "Joe")
         | 
| 13 | 
            +
                  def call(result = nil, **arguments)
         | 
| 14 | 
            +
                    result = Result.to_result(result).merge!(arguments)
         | 
| 15 15 | 
             
                    new(result)._call
         | 
| 16 16 | 
             
                    result
         | 
| 17 17 | 
             
                  end
         | 
| @@ -19,9 +19,9 @@ module ServiceActor | |
| 19 19 | 
             
                  # Call an actor with arguments. Returns the result and does not raise on
         | 
| 20 20 | 
             
                  # failure.
         | 
| 21 21 | 
             
                  #
         | 
| 22 | 
            -
                  #   CreateUser.result(name:  | 
| 23 | 
            -
                  def result( | 
| 24 | 
            -
                    call( | 
| 22 | 
            +
                  #   CreateUser.result(name: "Joe")
         | 
| 23 | 
            +
                  def result(result = nil, **arguments)
         | 
| 24 | 
            +
                    call(result, **arguments)
         | 
| 25 25 | 
             
                  rescue Failure => e
         | 
| 26 26 | 
             
                    e.result
         | 
| 27 27 | 
             
                  end
         | 
| @@ -16,11 +16,11 @@ module ServiceActor | |
| 16 16 |  | 
| 17 17 | 
             
                module PrependedMethods
         | 
| 18 18 | 
             
                  def _call
         | 
| 19 | 
            -
                    check_context_for_nil(self.class.inputs, origin:  | 
| 19 | 
            +
                    check_context_for_nil(self.class.inputs, origin: "input")
         | 
| 20 20 |  | 
| 21 21 | 
             
                    super
         | 
| 22 22 |  | 
| 23 | 
            -
                    check_context_for_nil(self.class.outputs, origin:  | 
| 23 | 
            +
                    check_context_for_nil(self.class.outputs, origin: "output")
         | 
| 24 24 | 
             
                  end
         | 
| 25 25 |  | 
| 26 26 | 
             
                  private
         | 
| @@ -31,7 +31,7 @@ module ServiceActor | |
| 31 31 |  | 
| 32 32 | 
             
                      raise ArgumentError,
         | 
| 33 33 | 
             
                            "The #{origin} \"#{name}\" on #{self.class} does not allow " \
         | 
| 34 | 
            -
                             | 
| 34 | 
            +
                            "nil values"
         | 
| 35 35 | 
             
                    end
         | 
| 36 36 | 
             
                  end
         | 
| 37 37 |  | 
| @@ -2,7 +2,7 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module ServiceActor
         | 
| 4 4 | 
             
              # Play class method to call a series of actors with the same result. On
         | 
| 5 | 
            -
              # failure, calls rollback on  | 
| 5 | 
            +
              # failure, calls rollback on actors that succeeded.
         | 
| 6 6 | 
             
              #
         | 
| 7 7 | 
             
              #   class CreateUser < Actor
         | 
| 8 8 | 
             
              #     play SaveUser,
         | 
| @@ -16,14 +16,6 @@ module ServiceActor | |
| 16 16 | 
             
                end
         | 
| 17 17 |  | 
| 18 18 | 
             
                module ClassMethods
         | 
| 19 | 
            -
                  def inherited(child)
         | 
| 20 | 
            -
                    super
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                    play_actors.each do |actor|
         | 
| 23 | 
            -
                      child.play_actors << actor
         | 
| 24 | 
            -
                    end
         | 
| 25 | 
            -
                  end
         | 
| 26 | 
            -
             | 
| 27 19 | 
             
                  def play(*actors, **options)
         | 
| 28 20 | 
             
                    actors.each do |actor|
         | 
| 29 21 | 
             
                      play_actors.push({ actor: actor, **options })
         | 
| @@ -33,6 +25,14 @@ module ServiceActor | |
| 33 25 | 
             
                  def play_actors
         | 
| 34 26 | 
             
                    @play_actors ||= []
         | 
| 35 27 | 
             
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def inherited(child)
         | 
| 30 | 
            +
                    super
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                    play_actors.each do |actor|
         | 
| 33 | 
            +
                      child.play_actors << actor
         | 
| 34 | 
            +
                    end
         | 
| 35 | 
            +
                  end
         | 
| 36 36 | 
             
                end
         | 
| 37 37 |  | 
| 38 38 | 
             
                module PrependedMethods
         | 
| @@ -61,6 +61,7 @@ module ServiceActor | |
| 61 61 |  | 
| 62 62 | 
             
                  def play_actor(actor)
         | 
| 63 63 | 
             
                    play_service_actor(actor) ||
         | 
| 64 | 
            +
                      play_symbol(actor) ||
         | 
| 64 65 | 
             
                      play_interactor(actor) ||
         | 
| 65 66 | 
             
                      actor.call(result)
         | 
| 66 67 | 
             
                  end
         | 
| @@ -75,9 +76,17 @@ module ServiceActor | |
| 75 76 | 
             
                    (@played ||= []).unshift(actor)
         | 
| 76 77 | 
             
                  end
         | 
| 77 78 |  | 
| 79 | 
            +
                  def play_symbol(actor)
         | 
| 80 | 
            +
                    return unless actor.is_a?(Symbol)
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                    send(actor)
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                    true
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
             | 
| 78 87 | 
             
                  def play_interactor(actor)
         | 
| 79 88 | 
             
                    return unless actor.is_a?(Class)
         | 
| 80 | 
            -
                    return unless actor.ancestors.map(&:name).include?( | 
| 89 | 
            +
                    return unless actor.ancestors.map(&:name).include?("Interactor")
         | 
| 81 90 |  | 
| 82 91 | 
             
                    result.merge!(actor.call(result).to_h)
         | 
| 83 92 | 
             
                  end
         | 
    
        data/lib/service_actor/result.rb
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 3 | 
            +
            require "ostruct"
         | 
| 4 4 |  | 
| 5 5 | 
             
            module ServiceActor
         | 
| 6 6 | 
             
              # Represents the context of an actor, holding the data from both its inputs
         | 
| @@ -51,5 +51,28 @@ module ServiceActor | |
| 51 51 | 
             
                def display
         | 
| 52 52 | 
             
                  to_h.fetch(:display)
         | 
| 53 53 | 
             
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                private
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def respond_to_missing?(method_name, include_private = false)
         | 
| 58 | 
            +
                  method_name.to_s.end_with?("?") || super
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                def method_missing(symbol, *args)
         | 
| 62 | 
            +
                  attribute = symbol.to_s.chomp("?")
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  if symbol.to_s.end_with?("?") && respond_to?(attribute)
         | 
| 65 | 
            +
                    define_singleton_method symbol do
         | 
| 66 | 
            +
                      attribute_value = send(attribute.to_sym)
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                      # Same as ActiveSupport’s #present?
         | 
| 69 | 
            +
                      attribute_value.respond_to?(:empty?) ? !attribute_value.empty? : !!attribute_value
         | 
| 70 | 
            +
                    end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                    return send(symbol)
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  super symbol, *args
         | 
| 76 | 
            +
                end
         | 
| 54 77 | 
             
              end
         | 
| 55 78 | 
             
            end
         | 
| @@ -7,7 +7,7 @@ module ServiceActor | |
| 7 7 | 
             
              # Example:
         | 
| 8 8 | 
             
              #
         | 
| 9 9 | 
             
              #   class ReduceOrderAmount < Actor
         | 
| 10 | 
            -
              #     input :order, type:  | 
| 10 | 
            +
              #     input :order, type: "Order"
         | 
| 11 11 | 
             
              #     input :amount, type: [Integer, Float]
         | 
| 12 12 | 
             
              #     input :bonus_applied, type: [TrueClass FalseClass]
         | 
| 13 13 | 
             
              #   end
         | 
| @@ -18,11 +18,11 @@ module ServiceActor | |
| 18 18 |  | 
| 19 19 | 
             
                module PrependedMethods
         | 
| 20 20 | 
             
                  def _call
         | 
| 21 | 
            -
                    check_type_definitions(self.class.inputs, kind:  | 
| 21 | 
            +
                    check_type_definitions(self.class.inputs, kind: "Input")
         | 
| 22 22 |  | 
| 23 23 | 
             
                    super
         | 
| 24 24 |  | 
| 25 | 
            -
                    check_type_definitions(self.class.outputs, kind:  | 
| 25 | 
            +
                    check_type_definitions(self.class.outputs, kind: "Output")
         | 
| 26 26 | 
             
                  end
         | 
| 27 27 |  | 
| 28 28 | 
             
                  private
         | 
    
        data/lib/service_actor.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: service_actor
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 3. | 
| 4 | 
            +
              version: 3.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Sunny Ripert
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2022- | 
| 11 | 
            +
            date: 2022-07-11 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: rspec
         | 
| @@ -53,19 +53,25 @@ dependencies: | |
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 54 | 
             
                    version: '0'
         | 
| 55 55 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 56 | 
            -
              name: rubocop
         | 
| 56 | 
            +
              name: rubocop-lts
         | 
| 57 57 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 58 | 
             
                requirements:
         | 
| 59 | 
            +
                - - "~>"
         | 
| 60 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            +
                    version: '12.0'
         | 
| 59 62 | 
             
                - - ">="
         | 
| 60 63 | 
             
                  - !ruby/object:Gem::Version
         | 
| 61 | 
            -
                    version:  | 
| 64 | 
            +
                    version: 12.0.1
         | 
| 62 65 | 
             
              type: :development
         | 
| 63 66 | 
             
              prerelease: false
         | 
| 64 67 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 68 | 
             
                requirements:
         | 
| 69 | 
            +
                - - "~>"
         | 
| 70 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 71 | 
            +
                    version: '12.0'
         | 
| 66 72 | 
             
                - - ">="
         | 
| 67 73 | 
             
                  - !ruby/object:Gem::Version
         | 
| 68 | 
            -
                    version:  | 
| 74 | 
            +
                    version: 12.0.1
         | 
| 69 75 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 70 76 | 
             
              name: rubocop-rspec
         | 
| 71 77 | 
             
              requirement: !ruby/object:Gem::Requirement
         |