operate 0.1.1 → 0.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 +5 -5
 - data/CHANGELOG.md +4 -0
 - data/README.md +78 -6
 - data/lib/operate/command.rb +26 -0
 - data/lib/operate/version.rb +1 -1
 - data/operate.gemspec +0 -8
 - metadata +3 -4
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 2 
     | 
    
         
            +
            SHA256:
         
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 32ca1e5fe8ebab826d9bffa0fffa21bc6d6dcba61de304839b4b8d66fdff6e5b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: a5ff2c95affdf3e82edff5d42a27c1c6a4683bbcb372d88c09069bbe5ded741e
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 79df511bc9ae931762d3dee5e8c7a7a256ffb4c2fc02999fc041c8dc32e917000f168378a364caba174894308764e8aa8295dd5974090ec88033b80e05749262
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: a2f0b35a8153cf465099d13148c34b6a9d8d16592d80555620f590dd42c48e162092e831c999a0b04c85ab4fe589ab0af542d9296109da7c3ac3e956e949feef
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -8,7 +8,7 @@ Use Operate to __remove business logic from your controller and model__, subsumi 
     | 
|
| 
       8 
8 
     | 
    
         
             
            "service" object that represents your processes. Examples might be: a user addition, a post addition, 
         
     | 
| 
       9 
9 
     | 
    
         
             
            or adding a comment.  
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
            Service objects can out  
     | 
| 
      
 11 
     | 
    
         
            +
            Service objects can factor out behavior that would bloat models or controllers, and is a useful step to patterns
         
     | 
| 
       12 
12 
     | 
    
         
             
            like Strategy and Command.
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            Service objects are not a new concept, and extracting controller bloat to service objects is a common 
         
     | 
| 
         @@ -22,9 +22,7 @@ exposed via `Operate::Command`, however, is solid and no breaking changes there 
     | 
|
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
            ## Dependencies
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
            Additionally, if ActiveRecord is available, transactions are supported. There is no explicit support for other ORMs.
         
     | 
| 
      
 25 
     | 
    
         
            +
            If ActiveRecord is available, transactions are supported. There is no explicit support for other ORMs.
         
     | 
| 
       28 
26 
     | 
    
         | 
| 
       29 
27 
     | 
    
         
             
            It's not required, but a form object library like [Reform] is recommended. Reform is used in the examples below.
         
     | 
| 
       30 
28 
     | 
    
         | 
| 
         @@ -57,9 +55,10 @@ Methods used in your service class: 
     | 
|
| 
       57 
55 
     | 
    
         | 
| 
       58 
56 
     | 
    
         
             
            Methods used by clients (normally a controller) of your service class:
         
     | 
| 
       59 
57 
     | 
    
         
             
            * `#on(*events, &block)` that subscribe to an event or events, and provide a block to handle that event
         
     | 
| 
      
 58 
     | 
    
         
            +
            * `#expose(hash)` called within a block passed to `#on` will set the hash as instance variables on the caller (typically a controller)
         
     | 
| 
       60 
59 
     | 
    
         | 
| 
       61 
60 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
      
 61 
     | 
    
         
            +
            ### A basic service
         
     | 
| 
       63 
62 
     | 
    
         | 
| 
       64 
63 
     | 
    
         
             
            ```ruby
         
     | 
| 
       65 
64 
     | 
    
         
             
            # put in app/services, app/commands, or something like that
         
     | 
| 
         @@ -114,11 +113,84 @@ end 
     | 
|
| 
       114 
113 
     | 
    
         
             
            Note: this example does not use [Strong Parameters] as [Reform] provides an explicit form property layout.
         
     | 
| 
       115 
114 
     | 
    
         | 
| 
       116 
115 
     | 
    
         | 
| 
      
 116 
     | 
    
         
            +
            ### Passing parameters
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
            You can pass parameters to the handling block by supplying the parameters as arguments to `broadcast`.
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 121 
     | 
    
         
            +
            # Your service
         
     | 
| 
      
 122 
     | 
    
         
            +
            class UserAddition
         
     | 
| 
      
 123 
     | 
    
         
            +
              include Operate::Command
         
     | 
| 
      
 124 
     | 
    
         
            +
              def call
         
     | 
| 
      
 125 
     | 
    
         
            +
                # ...
         
     | 
| 
      
 126 
     | 
    
         
            +
                broadcast(:ok, user)
         
     | 
| 
      
 127 
     | 
    
         
            +
              end
         
     | 
| 
      
 128 
     | 
    
         
            +
            end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
             
     | 
| 
      
 131 
     | 
    
         
            +
            # Your client (a controller):
         
     | 
| 
      
 132 
     | 
    
         
            +
            def create
         
     | 
| 
      
 133 
     | 
    
         
            +
              UserAddition.call(@form) do
         
     | 
| 
      
 134 
     | 
    
         
            +
                on(:ok) {|user| logger.info "#{user.name} created" }
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
            end
         
     | 
| 
      
 137 
     | 
    
         
            +
            ```
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
            ### Exposing values
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
            You can expose a value from within a handler block to the calling controller. Pass the values to expose as a hash.
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 144 
     | 
    
         
            +
            def new
         
     | 
| 
      
 145 
     | 
    
         
            +
              UserBuild.call(@form) do
         
     | 
| 
      
 146 
     | 
    
         
            +
                on(:ok) do |user|
         
     | 
| 
      
 147 
     | 
    
         
            +
            	  expose(user: user)
         
     | 
| 
      
 148 
     | 
    
         
            +
            	  render :new  # new.html.erb can access @user
         
     | 
| 
      
 149 
     | 
    
         
            +
            	end
         
     | 
| 
      
 150 
     | 
    
         
            +
              end
         
     | 
| 
      
 151 
     | 
    
         
            +
            end
         
     | 
| 
      
 152 
     | 
    
         
            +
            ```
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
            ## Testing
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
            A straight-forward way to test the events broadcast by an `Operate::Command` implementor:
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 159 
     | 
    
         
            +
            class UserAddition
         
     | 
| 
      
 160 
     | 
    
         
            +
              include Operate::Command
         
     | 
| 
      
 161 
     | 
    
         
            +
              # ...
         
     | 
| 
      
 162 
     | 
    
         
            +
              def call
         
     | 
| 
      
 163 
     | 
    
         
            +
                return broadcast(:invalid) if form.invalid?
         
     | 
| 
      
 164 
     | 
    
         
            +
                # ...
         
     | 
| 
      
 165 
     | 
    
         
            +
                broadcast(:ok) 
         
     | 
| 
      
 166 
     | 
    
         
            +
              end
         
     | 
| 
      
 167 
     | 
    
         
            +
            end
         
     | 
| 
      
 168 
     | 
    
         
            +
            ```
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
      
 170 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 171 
     | 
    
         
            +
            describe UserAddition do
         
     | 
| 
      
 172 
     | 
    
         
            +
              it 'broadcasts ok when creating user' do
         
     | 
| 
      
 173 
     | 
    
         
            +
                is_ok = false
         
     | 
| 
      
 174 
     | 
    
         
            +
                UserAddition.call(attributes_for(:new_user)) do
         
     | 
| 
      
 175 
     | 
    
         
            +
                  on(:ok) { is_ok = true }
         
     | 
| 
      
 176 
     | 
    
         
            +
                end
         
     | 
| 
      
 177 
     | 
    
         
            +
                expect(is_ok).to eq true
         
     | 
| 
      
 178 
     | 
    
         
            +
              end
         
     | 
| 
      
 179 
     | 
    
         
            +
              it 'broadcasts invalid when user validation fails' do
         
     | 
| 
      
 180 
     | 
    
         
            +
                is_invalid = false
         
     | 
| 
      
 181 
     | 
    
         
            +
                UserAddition.call(attributes_for(:invalid_user)) do
         
     | 
| 
      
 182 
     | 
    
         
            +
                  on(:invalid) { is_invalid = true }
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
                expect(is_invalid).to eq true
         
     | 
| 
      
 185 
     | 
    
         
            +
              end
         
     | 
| 
      
 186 
     | 
    
         
            +
            end
         
     | 
| 
      
 187 
     | 
    
         
            +
            ```
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
       117 
189 
     | 
    
         
             
            ## Credit
         
     | 
| 
       118 
190 
     | 
    
         | 
| 
       119 
191 
     | 
    
         
             
            The core of Operate is based on [rectify] and [wisper], and would not exist without these fine projects.
         
     | 
| 
       120 
192 
     | 
    
         
             
            Both rectify and wisper are excellent gems, they just provide more functionality than I require, and with
         
     | 
| 
       121 
     | 
    
         
            -
            some philosophical differences in execution (rectify requires you extend their base class, operate provides mixins).
         
     | 
| 
      
 193 
     | 
    
         
            +
            some philosophical differences in execution (rectify requires you to extend their base class, while operate provides mixins).
         
     | 
| 
       122 
194 
     | 
    
         | 
| 
       123 
195 
     | 
    
         | 
| 
       124 
196 
     | 
    
         
             
            ## Contributing
         
     | 
    
        data/lib/operate/command.rb
    CHANGED
    
    | 
         @@ -6,6 +6,7 @@ module Operate 
     | 
|
| 
       6 
6 
     | 
    
         
             
              # `register` handlers with on().
         
     | 
| 
       7 
7 
     | 
    
         
             
              # `broadcast` results with broadcast().
         
     | 
| 
       8 
8 
     | 
    
         
             
              # `transaction` wraps ActiveRecord transactions.
         
     | 
| 
      
 9 
     | 
    
         
            +
              # `expose` to set a value from the handler block to the caller
         
     | 
| 
       9 
10 
     | 
    
         
             
              #
         
     | 
| 
       10 
11 
     | 
    
         
             
              module Command
         
     | 
| 
       11 
12 
     | 
    
         
             
                include Operate::Pubsub::Publisher
         
     | 
| 
         @@ -17,12 +18,19 @@ module Operate 
     | 
|
| 
       17 
18 
     | 
    
         
             
                end
         
     | 
| 
       18 
19 
     | 
    
         | 
| 
       19 
20 
     | 
    
         
             
                module ClassMethods
         
     | 
| 
      
 21 
     | 
    
         
            +
                  attr_reader :command_presenter
         
     | 
| 
      
 22 
     | 
    
         
            +
                  
         
     | 
| 
       20 
23 
     | 
    
         
             
                  # Call will initialize the class with *args and invoke instance method `call` with no arguments
         
     | 
| 
       21 
24 
     | 
    
         
             
                  def call(*args, &block)
         
     | 
| 
       22 
25 
     | 
    
         
             
                    command = new(*args)
         
     | 
| 
       23 
26 
     | 
    
         
             
                    command.evaluate(&block) if block_given?
         
     | 
| 
       24 
27 
     | 
    
         
             
                    command.call
         
     | 
| 
       25 
28 
     | 
    
         
             
                  end
         
     | 
| 
      
 29 
     | 
    
         
            +
                  
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # def presenter presenter
         
     | 
| 
      
 31 
     | 
    
         
            +
                  #   @command_presenter = presenter
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #   self
         
     | 
| 
      
 33 
     | 
    
         
            +
                  # end
         
     | 
| 
       26 
34 
     | 
    
         
             
                end
         
     | 
| 
       27 
35 
     | 
    
         | 
| 
       28 
36 
     | 
    
         
             
                def transaction(&block)
         
     | 
| 
         @@ -51,5 +59,23 @@ module Operate 
     | 
|
| 
       51 
59 
     | 
    
         
             
                def respond_to_missing?(method_name, include_private = false)
         
     | 
| 
       52 
60 
     | 
    
         
             
                  @caller.respond_to?(method_name, include_private)
         
     | 
| 
       53 
61 
     | 
    
         
             
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
                
         
     | 
| 
      
 63 
     | 
    
         
            +
                #
         
     | 
| 
      
 64 
     | 
    
         
            +
                # Expose a value within a handler block to the caller.
         
     | 
| 
      
 65 
     | 
    
         
            +
                # Sets attribute directly if available, or as an instance variable.
         
     | 
| 
      
 66 
     | 
    
         
            +
                #
         
     | 
| 
      
 67 
     | 
    
         
            +
                # RegisterAccount.call(@form) do
         
     | 
| 
      
 68 
     | 
    
         
            +
                #   on(:ok) { |user| expose(:user => user) }
         
     | 
| 
      
 69 
     | 
    
         
            +
                # end
         
     | 
| 
      
 70 
     | 
    
         
            +
                #
         
     | 
| 
      
 71 
     | 
    
         
            +
                def expose(presentation_data)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  presentation_data.each do |attribute, value|
         
     | 
| 
      
 73 
     | 
    
         
            +
                    if @caller.respond_to?("#{attribute}=")
         
     | 
| 
      
 74 
     | 
    
         
            +
                      @caller.public_send("#{attribute}=", value)
         
     | 
| 
      
 75 
     | 
    
         
            +
                    else
         
     | 
| 
      
 76 
     | 
    
         
            +
                      @caller.instance_variable_set("@#{attribute}", value)
         
     | 
| 
      
 77 
     | 
    
         
            +
                    end
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
       54 
80 
     | 
    
         
             
              end
         
     | 
| 
       55 
81 
     | 
    
         
             
            end
         
     | 
    
        data/lib/operate/version.rb
    CHANGED
    
    
    
        data/operate.gemspec
    CHANGED
    
    | 
         @@ -14,14 +14,6 @@ Gem::Specification.new do |spec| 
     | 
|
| 
       14 
14 
     | 
    
         
             
              spec.homepage      = 'https://github.com/tomichj/operate'
         
     | 
| 
       15 
15 
     | 
    
         
             
              spec.license       = 'MIT'
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
              # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
         
     | 
| 
       18 
     | 
    
         
            -
              # to allow pushing to a single host or delete this section to allow pushing to any host.
         
     | 
| 
       19 
     | 
    
         
            -
              # if spec.respond_to?(:metadata)
         
     | 
| 
       20 
     | 
    
         
            -
              #   spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
         
     | 
| 
       21 
     | 
    
         
            -
              # else
         
     | 
| 
       22 
     | 
    
         
            -
              #   raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
         
     | 
| 
       23 
     | 
    
         
            -
              # end
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
17 
     | 
    
         
             
              spec.files         = `git ls-files -z`.split("\x0").reject do |f|
         
     | 
| 
       26 
18 
     | 
    
         
             
                f.match(%r{^(test|spec|features)/})
         
     | 
| 
       27 
19 
     | 
    
         
             
              end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: operate
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.2.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Justin Tomich
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2019-02-23 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: bundler
         
     | 
| 
         @@ -124,8 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       124 
124 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       125 
125 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       126 
126 
     | 
    
         
             
            requirements: []
         
     | 
| 
       127 
     | 
    
         
            -
             
     | 
| 
       128 
     | 
    
         
            -
            rubygems_version: 2.6.11
         
     | 
| 
      
 127 
     | 
    
         
            +
            rubygems_version: 3.0.2
         
     | 
| 
       129 
128 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       130 
129 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       131 
130 
     | 
    
         
             
            summary: Create service objects with Operate.
         
     |