operate 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e4ae06d376016ee482b1fe2c0fb7d15304f96f77
4
- data.tar.gz: '01248b745836660db7dedb802bf25de16d7c77a8'
2
+ SHA256:
3
+ metadata.gz: 32ca1e5fe8ebab826d9bffa0fffa21bc6d6dcba61de304839b4b8d66fdff6e5b
4
+ data.tar.gz: a5ff2c95affdf3e82edff5d42a27c1c6a4683bbcb372d88c09069bbe5ded741e
5
5
  SHA512:
6
- metadata.gz: 4b503d5be289f23dce63009daf120dedad7081ad42993d6934314d051f0dc2b9f0c8e68d21da81fe458fc2335e61384fa100b4cdfaa7e06309882de0970906fb
7
- data.tar.gz: 8f3c185e0a3b2f92e0d1a8384d8f91363f5562ad6028a6337cbe979fe73d9fdcfdf381a7777d7be8c8f34a85e0ab23624163cf5b8b91c2e4cc03eb7aad00c342
6
+ metadata.gz: 79df511bc9ae931762d3dee5e8c7a7a256ffb4c2fc02999fc041c8dc32e917000f168378a364caba174894308764e8aa8295dd5974090ec88033b80e05749262
7
+ data.tar.gz: a2f0b35a8153cf465099d13148c34b6a9d8d16592d80555620f590dd42c48e162092e831c999a0b04c85ab4fe589ab0af542d9296109da7c3ac3e956e949feef
@@ -1,5 +1,9 @@
1
1
  # Operate Changelog
2
2
 
3
+ ## [0.2.0] - February 23, 2019
4
+
5
+ - `expose` a value within a handler block to the caller
6
+
3
7
 
4
8
  ## [0.1.1] - October 27, 2017
5
9
 
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 factor behavior that would bloat models or controllers, and is a useful step to patterns
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
- Operate requires only `ActiveSupport` 4.2 or greater.
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
- An example service:
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Operate
2
- VERSION = '0.1.1'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -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.1.1
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: 2017-10-04 00:00:00.000000000 Z
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
- rubyforge_project:
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.