caze 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|