light_operations 0.0.9 → 0.1.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/.rubocop.yml +2 -1
- data/README.md +95 -25
- data/lib/light_operations/core.rb +12 -15
- data/lib/light_operations/version.rb +1 -1
- data/spec/lib/core_spec.rb +43 -11
- 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: 6b1cafc172727a76d2b73b15c1eaf8c16726dd4e
|
4
|
+
data.tar.gz: 5cbaaa590c2c85b73a440c2366f67960a789d02a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bd91a0435ba27b38faa56e17b0ea1ed94bc2b2a645858e9b7c1324a8b171447cf983a3e8b0de37af3b1795efc76feb4a45c0bc197f893497a888c40b034ad6b9
|
7
|
+
data.tar.gz: 9e29c25d4ccbd1da90da0ad9e8ad6b85ccda391663d1b280e27c7e9eb7c8258198c61ad523fbe1bdac899091620c3894836f37abfbd162df2468dedfa758e640
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -39,6 +39,71 @@ There is many possible usecases where and how you could use operations.
|
|
39
39
|
You can build csacade of opreations, use them one after the other,
|
40
40
|
use them recursively and a lot more.
|
41
41
|
|
42
|
+
|
43
|
+
Examples:
|
44
|
+
|
45
|
+
#### Simple
|
46
|
+
```ruby
|
47
|
+
require 'light_operations'
|
48
|
+
|
49
|
+
class CorrectNumber < LightOperations::Core
|
50
|
+
def execute(params)
|
51
|
+
params[:number] > 0 || fail!(:wrong_number)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
op = CorrectNumber.new
|
56
|
+
|
57
|
+
p op.run(number: 0).success? # return false
|
58
|
+
p op.run(number: 0).false? # return true
|
59
|
+
p op.run(number: 1).success? # return true
|
60
|
+
p op.run(number: 1).false? # return false
|
61
|
+
```
|
62
|
+
|
63
|
+
#### With active_model
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
require 'light_operations'
|
67
|
+
require 'active_model'
|
68
|
+
|
69
|
+
class Person
|
70
|
+
include ActiveModel::Model
|
71
|
+
|
72
|
+
attr_accessor :name, :age
|
73
|
+
validates_presence_of :name
|
74
|
+
end
|
75
|
+
|
76
|
+
class CreatePerson < LightOperations::Core
|
77
|
+
subject_name :person
|
78
|
+
def execute(params = {})
|
79
|
+
dependency(:repository).new(params).tap do |person|
|
80
|
+
person.valid?
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class FakeController
|
86
|
+
def create(params = {})
|
87
|
+
create_operation.run(params)
|
88
|
+
end
|
89
|
+
|
90
|
+
def create_operation
|
91
|
+
@create_operation ||= CreatePerson.new(repository: Person).bind_with(self).on(success: :render_success, fail: :render_fail)
|
92
|
+
end
|
93
|
+
|
94
|
+
def render_success(operation)
|
95
|
+
person = operation.person
|
96
|
+
puts "name: #{person.name}"
|
97
|
+
end
|
98
|
+
|
99
|
+
def render_fail(operation)
|
100
|
+
person, errors = operation.subject, operation.errors
|
101
|
+
puts errors.as_json
|
102
|
+
puts "name: #{person.name}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
```
|
42
107
|
Class
|
43
108
|
|
44
109
|
```ruby
|
@@ -60,9 +125,9 @@ You can add deferred actions for success and fail
|
|
60
125
|
|
61
126
|
```ruby
|
62
127
|
# 1
|
63
|
-
MyOperation.new.on_success { |
|
128
|
+
MyOperation.new.on_success { |operation| render :done, locals: { model: operation.subject } }
|
64
129
|
# 2
|
65
|
-
MyOperation.new.on(success: -> () { |
|
130
|
+
MyOperation.new.on(success: -> () { |operation| render :done, locals: { model: operation.subject } )
|
66
131
|
```
|
67
132
|
|
68
133
|
When you bind operation with other object you could delegate actions to binded object methods
|
@@ -104,24 +169,26 @@ operation.new(dependencies).tap do |op|
|
|
104
169
|
end
|
105
170
|
```
|
106
171
|
|
107
|
-
#### success block or method receive
|
108
|
-
|
172
|
+
#### success block or method receive operation as argument
|
173
|
+
##### operation.subject hold success object. You can use subject_name to create alias_method for subject
|
174
|
+
`(operation) -> { }`
|
109
175
|
|
110
176
|
or
|
111
177
|
|
112
178
|
```ruby
|
113
|
-
def success_method(
|
179
|
+
def success_method(operation)
|
114
180
|
...
|
115
181
|
end
|
116
182
|
|
117
183
|
```
|
118
|
-
#### fail block or method receive
|
119
|
-
|
184
|
+
#### fail block or method receive operation as argument
|
185
|
+
##### operation.subject, operation.errors hold failure object and errors. You can use subject_name to create alias_method for subject
|
186
|
+
`(operation) -> { }`
|
120
187
|
|
121
188
|
or
|
122
189
|
|
123
190
|
```ruby
|
124
|
-
def fail_method(
|
191
|
+
def fail_method(operation)
|
125
192
|
...
|
126
193
|
end
|
127
194
|
|
@@ -182,6 +249,7 @@ Operation
|
|
182
249
|
```ruby
|
183
250
|
class CollectFeedsOperation < LightOperations::Core
|
184
251
|
rescue_from Timeout::Error, with: :on_timeout
|
252
|
+
subject_name :news
|
185
253
|
|
186
254
|
def execute(params = {})
|
187
255
|
dependency(:http_client).get(params.fetch(:url)).body
|
@@ -208,14 +276,14 @@ class NewsFeedsController < ApplicationController
|
|
208
276
|
|
209
277
|
private
|
210
278
|
|
211
|
-
def second_attempt(
|
212
|
-
|
279
|
+
def second_attempt(operation)
|
280
|
+
operation
|
213
281
|
.on_fail(:display_old_news)
|
214
282
|
.run(url: BACKUP_NEWS_URL)
|
215
283
|
end
|
216
284
|
|
217
|
-
def display_news(
|
218
|
-
render :display_news, locals: { news: news }
|
285
|
+
def display_news(operation)
|
286
|
+
render :display_news, locals: { news: operation.news }
|
219
287
|
end
|
220
288
|
|
221
289
|
def display_old_news
|
@@ -237,6 +305,7 @@ Operation
|
|
237
305
|
|
238
306
|
```ruby
|
239
307
|
class AddBookOperation < LightOperations::Core
|
308
|
+
subject_name :book
|
240
309
|
def execute(params = {})
|
241
310
|
dependency(:book_model).new(params).tap do |model|
|
242
311
|
model.valid? # this method automatically provide errors from model.errors
|
@@ -266,11 +335,12 @@ class BooksController < ApplicationController
|
|
266
335
|
|
267
336
|
private
|
268
337
|
|
269
|
-
def book_created(
|
270
|
-
redirect_to :index, notice: "book #{book.name} created"
|
338
|
+
def book_created(operation)
|
339
|
+
redirect_to :index, notice: "book #{operation.book.name} created"
|
271
340
|
end
|
272
341
|
|
273
|
-
def render_book_form(
|
342
|
+
def render_book_form(operation=nil)
|
343
|
+
book = operation ? operation.book : Book.new
|
274
344
|
render :new, locals: { book: book }
|
275
345
|
end
|
276
346
|
|
@@ -291,7 +361,7 @@ Operation
|
|
291
361
|
```ruby
|
292
362
|
class AuthOperation < LightOperations::Core
|
293
363
|
rescue_from AuthFail, with: :on_auth_error
|
294
|
-
|
364
|
+
subject_name :account
|
295
365
|
def execute(params = {})
|
296
366
|
dependency(:auth_service).login(login: login(params), password: password(params))
|
297
367
|
end
|
@@ -328,13 +398,13 @@ class AuthController < ApplicationController
|
|
328
398
|
|
329
399
|
private
|
330
400
|
|
331
|
-
def create_session_with_dashbord_redirection(
|
332
|
-
session_create_for(account)
|
401
|
+
def create_session_with_dashbord_redirection(operation)
|
402
|
+
session_create_for(operation.account)
|
333
403
|
redirect_to :dashboard
|
334
404
|
end
|
335
405
|
|
336
|
-
def render_account_with_errors(
|
337
|
-
render :new, locals: { account: account }
|
406
|
+
def render_account_with_errors(operation)
|
407
|
+
render :new, locals: { account: operation.account }
|
338
408
|
end
|
339
409
|
|
340
410
|
def auth_op
|
@@ -357,8 +427,8 @@ class AuthController < ApplicationController
|
|
357
427
|
|
358
428
|
def create
|
359
429
|
auth_op
|
360
|
-
.on_success{ |
|
361
|
-
.on_fail { |
|
430
|
+
.on_success{ |op| create_session_with_dashbord_redirection(op.account) }
|
431
|
+
.on_fail { |op| render :new, locals: { account: op.account } }
|
362
432
|
.run(params)
|
363
433
|
end
|
364
434
|
|
@@ -394,14 +464,14 @@ class AuthController < ApplicationController
|
|
394
464
|
private
|
395
465
|
|
396
466
|
def go_to_dashboard
|
397
|
-
-> (
|
398
|
-
session_create_for(account)
|
467
|
+
-> (op) do
|
468
|
+
session_create_for(op.account)
|
399
469
|
redirect_to :dashboard
|
400
470
|
end
|
401
471
|
end
|
402
472
|
|
403
473
|
def go_to_login
|
404
|
-
-> (
|
474
|
+
-> (op) { render :new, locals: { account: op.account } }
|
405
475
|
end
|
406
476
|
|
407
477
|
def auth_op
|
@@ -5,7 +5,11 @@ module LightOperations
|
|
5
5
|
include ::ActiveSupport::Rescuable
|
6
6
|
MissingDependency = Class.new(StandardError)
|
7
7
|
|
8
|
-
attr_reader :
|
8
|
+
attr_reader :subject
|
9
|
+
|
10
|
+
def self.subject_name(method_name)
|
11
|
+
send(:define_method, method_name, proc { self.subject })
|
12
|
+
end
|
9
13
|
|
10
14
|
def initialize(dependencies = {})
|
11
15
|
@dependencies = dependencies
|
@@ -78,28 +82,21 @@ module LightOperations
|
|
78
82
|
|
79
83
|
protected
|
80
84
|
|
81
|
-
attr_reader :fail_errors
|
85
|
+
attr_reader :dependencies, :bind_object, :fail_errors
|
82
86
|
|
83
87
|
def actions_assign(hash, *keys)
|
84
88
|
keys.each { |key| actions[key] = hash[key] if hash.key?(key) }
|
85
89
|
end
|
86
90
|
|
87
91
|
def execute_actions
|
88
|
-
success? ?
|
89
|
-
end
|
90
|
-
|
91
|
-
def execute_success_action
|
92
|
-
return unless actions.key?(:success)
|
93
|
-
action = actions[:success]
|
94
|
-
bind_object.send(action, subject) if action.is_a?(Symbol) && bind_object
|
95
|
-
action.call(subject) if action.is_a?(Proc)
|
92
|
+
success? ? execute_action_kind(:success) : execute_action_kind(:fail)
|
96
93
|
end
|
97
94
|
|
98
|
-
def
|
99
|
-
return unless actions.key?(
|
100
|
-
action = actions[
|
101
|
-
bind_object.send(action,
|
102
|
-
action.call(
|
95
|
+
def execute_action_kind(kind)
|
96
|
+
return unless actions.key?(kind)
|
97
|
+
action = actions[kind]
|
98
|
+
bind_object.send(action, self) if action.is_a?(Symbol) && bind_object
|
99
|
+
action.call(self) if action.is_a?(Proc)
|
103
100
|
end
|
104
101
|
|
105
102
|
def fail!(fail_obj = true)
|
data/spec/lib/core_spec.rb
CHANGED
@@ -8,9 +8,9 @@ describe LightOperations::Core do
|
|
8
8
|
let(:binding_object) do
|
9
9
|
Class.new(Object).tap do |klass|
|
10
10
|
klass.class_eval do
|
11
|
-
def success_action(
|
11
|
+
def success_action(_operation); end
|
12
12
|
|
13
|
-
def error_action(
|
13
|
+
def error_action(_operaation); end
|
14
14
|
end
|
15
15
|
end.new
|
16
16
|
end
|
@@ -27,6 +27,17 @@ describe LightOperations::Core do
|
|
27
27
|
expect { subject.on(success: :do_nothing).run }.to raise_error('Not implemented yet')
|
28
28
|
end
|
29
29
|
|
30
|
+
it '.subject_name' do
|
31
|
+
test_obj = subject_factory do
|
32
|
+
subject_name :order
|
33
|
+
def execute(params)
|
34
|
+
params[:done] || fail!(:error)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
test_obj.run(done: :success)
|
38
|
+
expect(test_obj.order).to eq(:success)
|
39
|
+
end
|
40
|
+
|
30
41
|
context 'use cases' do
|
31
42
|
# dependency using
|
32
43
|
|
@@ -112,12 +123,12 @@ describe LightOperations::Core do
|
|
112
123
|
|
113
124
|
context '#on_success' do
|
114
125
|
it 'when bind_with and send_method is used' do
|
115
|
-
expect(binding_object).to receive(:success_action).with(
|
126
|
+
expect(binding_object).to receive(:success_action).with(subject)
|
116
127
|
subject.on_success(:success_action).bind_with(binding_object).run
|
117
128
|
end
|
118
129
|
|
119
130
|
it 'when block is used' do
|
120
|
-
subject.on_success { |
|
131
|
+
subject.on_success { |operation| expect(operation.subject).to eq(:success) }.run
|
121
132
|
end
|
122
133
|
end
|
123
134
|
|
@@ -172,14 +183,14 @@ describe LightOperations::Core do
|
|
172
183
|
|
173
184
|
context '#on_fail' do
|
174
185
|
it 'when bind_with and send_method is used' do
|
175
|
-
expect(binding_object).to receive(:error_action).with(
|
186
|
+
expect(binding_object).to receive(:error_action).with(subject)
|
176
187
|
subject.bind_with(binding_object).on_fail(:error_action).run
|
177
188
|
end
|
178
189
|
|
179
190
|
it 'when block is used' do
|
180
|
-
subject.on_fail do |
|
181
|
-
expect(
|
182
|
-
expect(errors).to eq([email: :unknown])
|
191
|
+
subject.on_fail do |operation|
|
192
|
+
expect(operation.subject).to eq(:fail)
|
193
|
+
expect(operation.errors).to eq([email: :unknown])
|
183
194
|
end
|
184
195
|
subject.run
|
185
196
|
end
|
@@ -202,7 +213,7 @@ describe LightOperations::Core do
|
|
202
213
|
context 'prepare operation to reuse or simply clear' do
|
203
214
|
it '#unbind!' do
|
204
215
|
subject.bind_with(:some_object)
|
205
|
-
expect { subject.unbind! }.to change { subject.bind_object }
|
216
|
+
expect { subject.unbind! }.to change { subject.send(:bind_object) }
|
206
217
|
.from(:some_object)
|
207
218
|
.to(nil)
|
208
219
|
end
|
@@ -235,6 +246,27 @@ describe LightOperations::Core do
|
|
235
246
|
end
|
236
247
|
end
|
237
248
|
|
249
|
+
context '#fail! in execute when is without arguments' do
|
250
|
+
subject do
|
251
|
+
subject_factory do
|
252
|
+
def execute(params = {})
|
253
|
+
fail! unless params.key?(:result)
|
254
|
+
params[:result]
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'setup operation in fail state' do
|
260
|
+
expect(subject.run.success?).to eq(false)
|
261
|
+
expect(subject.run.fail?).to eq(true)
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'setup operation in fail state' do
|
265
|
+
expect(subject.run(result: 'ok').success?).to eq(true)
|
266
|
+
expect(subject.run(result: 'ok').fail?).to eq(false)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
238
270
|
context 'Operation executed several times' do
|
239
271
|
subject do
|
240
272
|
subject_factory do
|
@@ -250,9 +282,9 @@ describe LightOperations::Core do
|
|
250
282
|
.bind_with(binding_object)
|
251
283
|
.on(success: :success_action, fail: :error_action)
|
252
284
|
|
253
|
-
expect(binding_object).to receive(:error_action).with(
|
285
|
+
expect(binding_object).to receive(:error_action).with(subject)
|
254
286
|
subject.run
|
255
|
-
expect(binding_object).to receive(:success_action).with(
|
287
|
+
expect(binding_object).to receive(:success_action).with(subject)
|
256
288
|
subject.run(result: :success)
|
257
289
|
end
|
258
290
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: light_operations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pawel Niemczyk
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|