caze 0.0.2 → 0.0.3
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 +75 -33
- data/caze.gemspec +1 -1
- data/lib/caze.rb +13 -21
- data/lib/caze/version.rb +1 -1
- data/spec/caze_spec.rb +25 -36
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57f420be075d3ee1de9347c5635e710ff4efd795
|
4
|
+
data.tar.gz: e2de97c3f2916ecdf8711c947ee651692a532c58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8320bc671bc0d8608ae61539c21cbd04a67f925747d541682ceb27b9843937a5d6ef4118b21c9f73f71317d5cfd566712a2ac54cd0cbec7bcf16202f026a2d0b
|
7
|
+
data.tar.gz: dbde77a1170fb8689e8d7f17f67eaeb89b4e4359efc538b6ea8ea2514e240d1ade7dee316adbf15cd0437def582e4ad2a90c505c7007246d7005965cbee8226f
|
data/README.md
CHANGED
@@ -1,74 +1,116 @@
|
|
1
1
|
# Caze
|
2
2
|
|
3
|
-
This is a simple DSL to
|
4
|
-
The
|
5
|
-
use cases entry points inside the main project file.
|
3
|
+
This is a simple DSL to declare use cases as entry points of a module.
|
4
|
+
The purpose is to avoid the verbose declarations.
|
6
5
|
|
7
6
|
## Usage
|
8
7
|
|
9
|
-
|
10
|
-
and include it in your main module "class".
|
8
|
+
Instead of doing this:
|
11
9
|
|
12
10
|
```ruby
|
13
|
-
|
11
|
+
module Project
|
12
|
+
def self.sum(x, y)
|
13
|
+
UseCases::Sum.execute(x, y)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.subtract(x, y)
|
17
|
+
UseCases::Subtract.execute(x, y)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
```
|
21
|
+
|
22
|
+
You can do this:
|
14
23
|
|
15
|
-
|
24
|
+
```ruby
|
16
25
|
require 'caze'
|
17
|
-
require 'project/use_cases/foo'
|
18
26
|
|
19
27
|
module Project
|
20
28
|
include Caze
|
21
29
|
|
22
|
-
|
30
|
+
has_use_case sum: UseCases::Sum,
|
31
|
+
has_use_case subtract: UseCases::Subtract
|
23
32
|
end
|
24
33
|
```
|
25
34
|
|
26
|
-
|
35
|
+
## Using transactions
|
36
|
+
|
37
|
+
You can use transactions in your use cases by providing a `transaction_handler`
|
38
|
+
in your module. The only method that transaction handler should
|
39
|
+
respond is `#transaction`.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Project.transaction_handler = ActiveRecord::Base
|
43
|
+
```
|
44
|
+
|
45
|
+
While declaring which use cases your app has, you can set the option
|
46
|
+
`transactional` to `true`.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
has_use_case wow: UseCases::Wow, transactional: true
|
50
|
+
```
|
51
|
+
|
52
|
+
Note that the transaction handler must implement `#transaction` and
|
53
|
+
return the value inside the block. It will also be responsible for handle errors
|
54
|
+
and rollback if necessary.
|
55
|
+
|
56
|
+
## Exporting instance methods as class methods
|
57
|
+
|
58
|
+
Inside the use case classes you can use the `.export` method, so in the `UseCases::Sum` instead of this:
|
27
59
|
|
28
60
|
```ruby
|
29
61
|
module Project
|
30
62
|
module UseCases
|
31
|
-
class
|
32
|
-
|
63
|
+
class Sum
|
64
|
+
def self.execute(x ,y)
|
65
|
+
new(x,y).foo
|
66
|
+
end
|
33
67
|
|
34
|
-
|
68
|
+
def initialize(x, y)
|
69
|
+
@x = x
|
70
|
+
@y = y
|
71
|
+
end
|
35
72
|
|
36
|
-
def
|
37
|
-
|
73
|
+
def sum
|
74
|
+
x + y
|
38
75
|
end
|
39
76
|
end
|
40
77
|
end
|
41
78
|
end
|
42
79
|
```
|
43
80
|
|
44
|
-
|
81
|
+
You can define a class method based on an instance method with `export`:
|
45
82
|
|
46
83
|
```ruby
|
47
|
-
Project
|
48
|
-
|
84
|
+
module Project
|
85
|
+
module UseCases
|
86
|
+
class Foo
|
87
|
+
include Caze
|
49
88
|
|
50
|
-
|
89
|
+
export :sum, as: :execute
|
51
90
|
|
52
|
-
|
53
|
-
|
54
|
-
|
91
|
+
def initialize(x, y)
|
92
|
+
@x = x
|
93
|
+
@y = y
|
94
|
+
end
|
55
95
|
|
56
|
-
|
57
|
-
|
96
|
+
def sum
|
97
|
+
x + y
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
58
102
|
```
|
59
103
|
|
60
|
-
|
61
|
-
|
104
|
+
The `as` param, tells how the class method must be named,
|
105
|
+
if it is not passed the class method will have the of the instance method.
|
106
|
+
|
107
|
+
|
108
|
+
With this you can call your project use cases without the need to know its internals:
|
62
109
|
|
63
110
|
```ruby
|
64
|
-
|
111
|
+
Project.sum(4, 2) # This will call sum inside the use case `UseCases::Sum`
|
65
112
|
```
|
66
113
|
|
67
|
-
|
68
|
-
return the value inside the block. It will also be responsible for handle errors
|
69
|
-
and rollback if necessary.
|
70
|
-
|
71
|
-
# License
|
114
|
+
# Apache License 2.0
|
72
115
|
|
73
|
-
Apache License 2.0
|
74
116
|
Check LICENSE.txt
|
data/caze.gemspec
CHANGED
@@ -6,7 +6,7 @@ require 'caze/version'
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "caze"
|
8
8
|
spec.version = Caze::VERSION
|
9
|
-
spec.authors = ["
|
9
|
+
spec.authors = ["Philip Sampaio", "Fabiano Beselga"]
|
10
10
|
spec.email = ["philip@magnetis.com.br", "fabiano@magnetis.com.br"]
|
11
11
|
spec.summary = %q{A DSL to define use cases}
|
12
12
|
spec.description = %q{With Caze it's easy to define use cases and entry points.}
|
data/lib/caze.rb
CHANGED
@@ -10,36 +10,28 @@ module Caze
|
|
10
10
|
module ClassMethods
|
11
11
|
attr_accessor :transaction_handler
|
12
12
|
|
13
|
-
def
|
14
|
-
|
15
|
-
main_module = self
|
13
|
+
def has_use_case(use_case_name, use_case_class, options = {})
|
14
|
+
transactional = options.fetch(:transactional) { false }
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
define_singleton_method(use_case_name, Proc.new { |*args|
|
17
|
+
if transactional
|
18
|
+
handler = self.transaction_handler
|
20
19
|
|
21
|
-
|
20
|
+
raise NoTransactionMethodError, "This action should be executed inside a transaction. But no transaction handler was configured." unless handler
|
21
|
+
|
22
|
+
handler.transaction { use_case_object.send(method_name) }
|
23
|
+
else
|
22
24
|
use_case_class.send(use_case_name, *args)
|
23
|
-
|
24
|
-
|
25
|
+
end
|
26
|
+
})
|
25
27
|
end
|
26
28
|
|
27
|
-
def
|
29
|
+
def export(method_name, options = {})
|
28
30
|
method_to_define = options.fetch(:as) { method_name }
|
29
|
-
use_transaction = options.fetch(:use_transaction) { false }
|
30
31
|
|
31
32
|
define_singleton_method(method_to_define, Proc.new { |*args|
|
32
33
|
use_case_object = args.empty? ? new : new(*args)
|
33
|
-
|
34
|
-
if use_transaction
|
35
|
-
handler = parent_module.transaction_handler
|
36
|
-
|
37
|
-
raise NoTransactionMethodError, "This action should be executed inside a transaction. But no transaction handler was configured." unless handler
|
38
|
-
|
39
|
-
handler.transaction { use_case_object.send(method_name) }
|
40
|
-
else
|
41
|
-
use_case_object.send(method_name)
|
42
|
-
end
|
34
|
+
use_case_object.send(method_name)
|
43
35
|
})
|
44
36
|
end
|
45
37
|
end
|
data/lib/caze/version.rb
CHANGED
data/spec/caze_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe Caze do
|
|
12
12
|
class DummyUseCase
|
13
13
|
include Caze
|
14
14
|
|
15
|
-
|
15
|
+
export :the_answer
|
16
16
|
|
17
17
|
def the_answer
|
18
18
|
42
|
@@ -22,7 +22,7 @@ describe Caze do
|
|
22
22
|
class DummyUseCaseWithParam
|
23
23
|
include Caze
|
24
24
|
|
25
|
-
|
25
|
+
export :the_answer_for
|
26
26
|
|
27
27
|
def initialize(question, priority: :low)
|
28
28
|
@priority = priority
|
@@ -36,15 +36,16 @@ describe Caze do
|
|
36
36
|
module Dummy
|
37
37
|
include Caze
|
38
38
|
|
39
|
-
|
40
|
-
|
39
|
+
has_use_case :the_answer, DummyUseCase
|
40
|
+
has_use_case :the_answer_for, DummyUseCaseWithParam
|
41
|
+
has_use_case :the_transactional_answer, DummyUseCase, transactional: true
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
44
45
|
let(:use_case) { DummyUseCase }
|
45
46
|
let(:app) { Dummy }
|
46
47
|
|
47
|
-
describe '.
|
48
|
+
describe '.has_use_case' do
|
48
49
|
it 'delegates the use case message to the use case' do
|
49
50
|
allow(use_case).to receive(:the_answer)
|
50
51
|
app.the_answer
|
@@ -55,56 +56,44 @@ describe Caze do
|
|
55
56
|
expect(app.the_answer_for('the meaning of life', priority: :high)).to eql([:high, 42])
|
56
57
|
end
|
57
58
|
end
|
58
|
-
end
|
59
|
-
|
60
|
-
describe '.define_entry_point' do
|
61
|
-
it 'defines a class method' do
|
62
|
-
expect(use_case).to respond_to(:the_answer)
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'using the flag `as`' do
|
66
|
-
before do
|
67
|
-
use_case.define_entry_point :the_answer, as: :universal_answer
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'defines an entry point with another name' do
|
71
|
-
expect(use_case).to respond_to(:universal_answer)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
59
|
|
76
60
|
context 'using transaction' do
|
77
61
|
context 'when there is a transaction method' do
|
78
|
-
let(:transaction_handler)
|
79
|
-
double(:transaction_handler)
|
80
|
-
end
|
62
|
+
let(:transaction_handler) { double(:transaction_handler) }
|
81
63
|
|
82
64
|
before do
|
83
65
|
app.transaction_handler = transaction_handler
|
84
|
-
use_case.define_entry_point :the_answer,
|
85
|
-
as: :the_answer_with_transaction,
|
86
|
-
use_transaction: true
|
87
66
|
end
|
88
67
|
|
89
68
|
it 'uses the transaction handler' do
|
90
69
|
expect(transaction_handler).to receive(:transaction)
|
91
|
-
|
70
|
+
app.the_transactional_answer
|
92
71
|
end
|
93
72
|
end
|
94
73
|
|
95
74
|
context 'when there is no transaction method defined' do
|
96
|
-
before do
|
97
|
-
use_case.define_entry_point :the_answer,
|
98
|
-
as: :the_answer_with_transaction,
|
99
|
-
use_transaction: true
|
100
|
-
end
|
101
|
-
|
102
75
|
it 'raises an exception' do
|
103
76
|
expect {
|
104
|
-
|
77
|
+
app.the_transactional_answer
|
105
78
|
}.to raise_error(/This action should be executed inside a transaction/)
|
106
79
|
end
|
107
80
|
end
|
108
81
|
end
|
109
82
|
end
|
83
|
+
|
84
|
+
describe '.export' do
|
85
|
+
it 'defines a class method' do
|
86
|
+
expect(use_case).to respond_to(:the_answer)
|
87
|
+
end
|
88
|
+
|
89
|
+
context 'using the flag `as`' do
|
90
|
+
before do
|
91
|
+
use_case.export :the_answer, as: :universal_answer
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'defines an entry point with another name' do
|
95
|
+
expect(use_case).to respond_to(:universal_answer)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
110
99
|
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caze
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Philip Sampaio
|
8
|
+
- Fabiano Beselga
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
12
|
+
date: 2015-02-16 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|