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 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.