prezzo 0.5.1 → 1.0.0.pre.rc
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +135 -127
- data/lib/prezzo.rb +3 -1
- data/lib/prezzo/calculator.rb +15 -9
- data/lib/prezzo/components_dsl.rb +46 -0
- data/lib/prezzo/context.rb +11 -25
- data/lib/prezzo/explainable.rb +8 -29
- data/lib/prezzo/params_dsl.rb +55 -0
- data/lib/prezzo/transient_dsl.rb +37 -0
- data/lib/prezzo/version.rb +1 -1
- data/prezzo.gemspec +0 -1
- metadata +8 -20
- data/lib/prezzo/composable.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4409631f03de4a6dff3ebfbb48f25a0e4e9dcac4
|
4
|
+
data.tar.gz: ff6c4ec10622aeb9e924cbbe6b4c9b95dbd4a12d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 40cb9eead217c8009abbc86225913d3d099dc603a98a4c421d832d021267986d3995bc44033aff88856ee41fb7b378ba4e80ca3127390bdcc514656eda4f81aa
|
7
|
+
data.tar.gz: 1201e28ad3e1aa9e2a76c238c4b702e41038a12aa4088560aee8ca79bde0df99a060930023ec4b8a5c531692baf1d7524927a29740eaf64189c7e1719cd26c81
|
data/README.md
CHANGED
@@ -23,215 +23,223 @@ $ gem install prezzo
|
|
23
23
|
|
24
24
|
## Usage
|
25
25
|
|
26
|
-
###
|
26
|
+
### The calculation context
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
`Prezzo::Context` is a source of data for your calculators. It receives a hash
|
29
|
+
of params and makes them available to calculators.
|
30
30
|
|
31
31
|
e.g.:
|
32
32
|
|
33
33
|
```ruby
|
34
|
-
|
35
|
-
|
36
|
-
include Prezzo::Context
|
37
|
-
CATEGORIES = ["UberX", "UberXL", "UberBlack"].freeze
|
38
|
-
|
39
|
-
validations do
|
40
|
-
required(:category).filled(included_in?: CATEGORIES)
|
41
|
-
required(:distance).filled(:float?)
|
42
|
-
required(:total_cars).filled(:int?)
|
43
|
-
required(:available_cars).filled(:int?)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
34
|
+
context = Prezzo::Context.new(category: "Expensive", distance: 10.0)
|
35
|
+
```
|
47
36
|
|
48
|
-
|
37
|
+
### Simple calculators
|
49
38
|
|
50
|
-
|
51
|
-
|
52
|
-
|
39
|
+
`Prezzo::Calculator` is the top level concept to describe calculations. Define
|
40
|
+
a `formula` method that describe the calculation you want to perform and call
|
41
|
+
the `calculate` method.
|
53
42
|
|
54
|
-
|
55
|
-
|
56
|
-
|
43
|
+
e.g.:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
require "prezzo"
|
57
47
|
|
58
|
-
|
59
|
-
|
48
|
+
class StaticCalculator
|
49
|
+
include Prezzo::Calculator
|
50
|
+
|
51
|
+
def formula
|
52
|
+
2 * 5
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
StaticCalculator.new.calculate
|
57
|
+
#=> 10
|
60
58
|
```
|
61
59
|
|
62
|
-
###
|
60
|
+
### Accessing context params
|
63
61
|
|
64
|
-
|
62
|
+
Use the `param` dsl to create methods that read data from the context.
|
65
63
|
|
66
64
|
e.g.:
|
67
65
|
|
68
66
|
```ruby
|
69
67
|
require "prezzo"
|
70
68
|
|
71
|
-
|
72
|
-
|
73
|
-
include Prezzo::Calculator
|
74
|
-
|
75
|
-
def calculate
|
76
|
-
price_per_kilometer * distance
|
77
|
-
end
|
69
|
+
class Multiplier
|
70
|
+
include Prezzo::Calculator
|
78
71
|
|
79
|
-
|
80
|
-
|
81
|
-
end
|
72
|
+
param :arg1
|
73
|
+
param :arg2
|
82
74
|
|
83
|
-
|
84
|
-
|
85
|
-
end
|
75
|
+
def formula
|
76
|
+
arg1 * arg2
|
86
77
|
end
|
87
78
|
end
|
88
79
|
|
89
|
-
context =
|
90
|
-
|
80
|
+
context = Prezzo::Context.new(arg1: 2, arg2: 10.0)
|
81
|
+
Multiplier.new(context).calculate
|
91
82
|
#=> 20.0
|
92
83
|
```
|
93
84
|
|
94
|
-
|
85
|
+
### Default params
|
95
86
|
|
96
|
-
|
97
|
-
|
98
|
-
### Prezzo::Composable
|
99
|
-
|
100
|
-
The `Prezzo::Composable` module is an abstraction that provides a nice way of injecting other calculators define how the price will be composed with all of those calculators.
|
87
|
+
The `param` dsl accepts a default value:
|
101
88
|
|
102
89
|
e.g.:
|
103
90
|
|
104
91
|
```ruby
|
105
92
|
require "prezzo"
|
106
93
|
|
107
|
-
|
108
|
-
|
109
|
-
include Prezzo::Calculator
|
110
|
-
include Prezzo::Composable
|
94
|
+
class OptionalCalculator
|
95
|
+
include Prezzo::Calculator
|
111
96
|
|
112
|
-
|
113
|
-
price_per_distance: PricePerDistanceCalculator,
|
97
|
+
param :optional, default: 10.0
|
114
98
|
|
115
|
-
|
116
|
-
|
117
|
-
end
|
99
|
+
def formula
|
100
|
+
optional * 3
|
118
101
|
end
|
119
102
|
end
|
120
103
|
|
121
|
-
context =
|
122
|
-
|
123
|
-
#=>
|
104
|
+
context = Prezzo::Context.new(arg1: 2, arg2: 10.0)
|
105
|
+
OptionalCalculator.new(context).calculate
|
106
|
+
#=> 30.0
|
124
107
|
```
|
125
108
|
|
126
|
-
###
|
109
|
+
### Nested context params
|
127
110
|
|
128
|
-
The `
|
111
|
+
The `param` dsl can take a block to access nested data in the context.
|
129
112
|
|
130
113
|
e.g.:
|
131
114
|
|
132
115
|
```ruby
|
133
116
|
require "prezzo"
|
134
117
|
|
135
|
-
|
136
|
-
|
137
|
-
include Prezzo::Calculator
|
138
|
-
include Prezzo::Composable
|
139
|
-
include Prezzo::Explainable
|
118
|
+
class NestedCalculator
|
119
|
+
include Prezzo::Calculator
|
140
120
|
|
141
|
-
|
142
|
-
|
143
|
-
|
121
|
+
param :level1 do
|
122
|
+
param :level2
|
123
|
+
end
|
144
124
|
|
145
|
-
|
146
|
-
|
147
|
-
end
|
125
|
+
def formula
|
126
|
+
level1.level2 * 2
|
148
127
|
end
|
149
128
|
end
|
150
129
|
|
151
|
-
context =
|
152
|
-
|
153
|
-
#=>
|
130
|
+
context = Prezzo::Context.new(level1: { level2: 10.0 })
|
131
|
+
NestedCalculator.new(context).calculate
|
132
|
+
#=> 20.0
|
154
133
|
```
|
155
134
|
|
156
|
-
|
135
|
+
### Composing calculators
|
157
136
|
|
158
|
-
`
|
137
|
+
Calculators provide the `component` dsl method to make it easy to compose
|
138
|
+
calculators. Each calculator will be defined as a method in the calculator.
|
139
|
+
They will receive the whole context on instantiation.
|
140
|
+
|
141
|
+
e.g.:
|
159
142
|
|
160
143
|
```ruby
|
161
|
-
|
162
|
-
|
144
|
+
require "prezzo"
|
145
|
+
|
146
|
+
class ComposedCalculator
|
147
|
+
include Prezzo::Calculator
|
148
|
+
|
149
|
+
component :calculator1, StaticCalculator
|
150
|
+
component :calculator2, Multiplier
|
163
151
|
|
164
|
-
|
165
|
-
|
152
|
+
def formula
|
153
|
+
calculator1 + calculator2
|
154
|
+
end
|
166
155
|
end
|
156
|
+
|
157
|
+
context = Prezzo::Context.new(arg1: 2, arg2: 10.0)
|
158
|
+
ComposedCalculator.new(context).calculate
|
159
|
+
#=> 30.0
|
167
160
|
```
|
168
161
|
|
169
|
-
|
162
|
+
### Restricting the context
|
163
|
+
|
164
|
+
You can restrict the context of each calculator by providing a third argument
|
165
|
+
to `components`:
|
166
|
+
|
167
|
+
e.g.:
|
170
168
|
|
171
169
|
```ruby
|
172
|
-
|
170
|
+
require "prezzo"
|
171
|
+
|
172
|
+
class RestrictedCalculator
|
173
173
|
include Prezzo::Calculator
|
174
|
-
include Prezzo::Explainable
|
175
174
|
|
176
|
-
|
175
|
+
component :calculator1, Multiplier, :side1
|
176
|
+
component :calculator2, Multiplier, :side2
|
177
177
|
|
178
|
-
def
|
179
|
-
|
178
|
+
def formula
|
179
|
+
calculator1 + calculator2
|
180
180
|
end
|
181
|
+
end
|
181
182
|
|
182
|
-
|
183
|
-
|
184
|
-
|
183
|
+
context = Prezzo::Context.new(side1: { arg1: 2, arg2: 10.0 }, side2: { arg1: 3, arg2: 20.0 })
|
184
|
+
RestrictedCalculator.new(context).calculate
|
185
|
+
#=> 80.0
|
186
|
+
```
|
185
187
|
|
186
|
-
|
187
|
-
20
|
188
|
-
end
|
189
|
-
end
|
188
|
+
### Explanations
|
190
189
|
|
191
|
-
|
192
|
-
|
193
|
-
include Prezzo::Composable
|
194
|
-
include Prezzo::Explainable
|
190
|
+
The `explain` method provides a nice way of representing how the price was
|
191
|
+
composed. It will include all params and components defined in the calculator.
|
195
192
|
|
196
|
-
|
193
|
+
e.g.:
|
197
194
|
|
198
|
-
|
195
|
+
```ruby
|
196
|
+
require "prezzo"
|
197
|
+
|
198
|
+
class ExplainableCalculator
|
199
|
+
include Prezzo::Calculator
|
199
200
|
|
200
|
-
|
201
|
-
|
201
|
+
param :value
|
202
|
+
component :calculator1, StaticCalculator
|
203
|
+
component :calculator2, Multiplier
|
204
|
+
|
205
|
+
def formula
|
206
|
+
value + calculator1 + calculator2
|
202
207
|
end
|
203
208
|
end
|
209
|
+
|
210
|
+
context = Prezzo::Context.new(value: 3, arg1: 2, arg2: 10.0)
|
211
|
+
ExplainableCalculator.new(context).explain
|
212
|
+
#=> { total: 33.0, context: { value: 3 }, components: { calculator1: { ... }, calculator2: { ... } } }
|
204
213
|
```
|
205
214
|
|
206
|
-
|
215
|
+
### Transient values
|
216
|
+
|
217
|
+
Intermediate calculation values that you would like to appear on the
|
218
|
+
explanation can be defined with the `transient` dsl:
|
207
219
|
|
208
220
|
```ruby
|
209
|
-
|
210
|
-
total: 35,
|
211
|
-
components: {
|
212
|
-
foo: 30
|
213
|
-
}
|
214
|
-
}
|
215
|
-
```
|
221
|
+
require "prezzo"
|
216
222
|
|
217
|
-
|
223
|
+
class TransientCalculator
|
224
|
+
include Prezzo::Calculator
|
218
225
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
bar: 10,
|
227
|
-
baz: 20
|
228
|
-
}
|
229
|
-
}
|
230
|
-
}
|
231
|
-
}
|
232
|
-
```
|
226
|
+
param :arg1
|
227
|
+
param :arg2
|
228
|
+
param :arg3
|
229
|
+
|
230
|
+
transient :intermediate do
|
231
|
+
arg1 + arg2
|
232
|
+
end
|
233
233
|
|
234
|
-
|
234
|
+
def formula
|
235
|
+
arg3 * intermediate
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
context = Prezzo::Context.new(arg1: 1, arg2: 2, arg3: 3)
|
240
|
+
TransientCalculator.new(context).explain
|
241
|
+
#=> { total: 9, context: { arg1: 1, arg2: 2, arg3: 3 }, transients: { intermediate: 3 } }
|
242
|
+
```
|
235
243
|
|
236
244
|
## Development
|
237
245
|
|
data/lib/prezzo.rb
CHANGED
@@ -2,7 +2,9 @@ require "prezzo/version"
|
|
2
2
|
|
3
3
|
module Prezzo
|
4
4
|
autoload :Calculator, "prezzo/calculator"
|
5
|
-
autoload :
|
5
|
+
autoload :ParamsDSL, "prezzo/params_dsl"
|
6
|
+
autoload :ComponentsDSL, "prezzo/components_dsl"
|
7
|
+
autoload :TransientDSL, "prezzo/transient_dsl"
|
6
8
|
autoload :Context, "prezzo/context"
|
7
9
|
autoload :Explainable, "prezzo/explainable"
|
8
10
|
end
|
data/lib/prezzo/calculator.rb
CHANGED
@@ -1,22 +1,28 @@
|
|
1
1
|
module Prezzo
|
2
2
|
module Calculator
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
base.include(ParamsDSL)
|
6
|
+
base.include(ComponentsDSL)
|
7
|
+
base.include(TransientDSL)
|
8
|
+
base.include(Explainable)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
3
12
|
def initialize(context = {})
|
4
|
-
@context =
|
13
|
+
@context = context
|
5
14
|
end
|
6
15
|
|
7
16
|
def calculate
|
8
|
-
|
17
|
+
@total ||= formula
|
18
|
+
end
|
19
|
+
|
20
|
+
def formula
|
21
|
+
raise "Formula not implemented"
|
9
22
|
end
|
10
23
|
|
11
24
|
private
|
12
25
|
|
13
26
|
attr_reader :context
|
14
|
-
|
15
|
-
def validated!(context)
|
16
|
-
raise "Empty Context" if context.nil?
|
17
|
-
raise "Invalid Context" if context.respond_to?(:valid?) && !context.valid?
|
18
|
-
|
19
|
-
context
|
20
|
-
end
|
21
27
|
end
|
22
28
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Prezzo
|
2
|
+
module ComponentsDSL
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def component(name, klass, sub_context_name = nil)
|
11
|
+
components << name
|
12
|
+
|
13
|
+
define_method(name) do
|
14
|
+
cached_components[name] ||=
|
15
|
+
begin
|
16
|
+
c = sub_context_name ? context.fetch(sub_context_name) : context
|
17
|
+
|
18
|
+
instance = klass.new(c)
|
19
|
+
instance.sub_context(sub_context_name) if sub_context_name
|
20
|
+
instance
|
21
|
+
end
|
22
|
+
|
23
|
+
cached_components[name].calculate
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def components
|
28
|
+
@components ||= []
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def compile_components
|
33
|
+
self.class.components.reduce({}) do |acc, name|
|
34
|
+
public_send(name) # force component cache
|
35
|
+
acc[name] = cached_components[name].explain
|
36
|
+
acc
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def cached_components
|
43
|
+
@cached_components ||= {}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/prezzo/context.rb
CHANGED
@@ -1,37 +1,23 @@
|
|
1
|
-
require "hanami-validations"
|
2
|
-
|
3
1
|
module Prezzo
|
4
|
-
|
5
|
-
|
6
|
-
base.class_eval do
|
7
|
-
base.include(Hanami::Validations)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def valid?
|
12
|
-
validation.success?
|
13
|
-
end
|
2
|
+
class Context
|
3
|
+
include ParamsDSL
|
14
4
|
|
15
|
-
def
|
16
|
-
|
5
|
+
def initialize(attributes)
|
6
|
+
@attributes = attributes
|
17
7
|
end
|
18
8
|
|
19
9
|
def fetch(key, default = nil)
|
20
|
-
|
21
|
-
|
10
|
+
value = @attributes.fetch(key, default)
|
11
|
+
|
12
|
+
if value.is_a?(Hash)
|
13
|
+
Class.new(Context).new(value)
|
22
14
|
else
|
23
|
-
|
15
|
+
value
|
24
16
|
end
|
25
17
|
end
|
26
18
|
|
27
|
-
def
|
28
|
-
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def validation
|
34
|
-
@_validation ||= validate
|
19
|
+
def context
|
20
|
+
self
|
35
21
|
end
|
36
22
|
end
|
37
23
|
end
|
data/lib/prezzo/explainable.rb
CHANGED
@@ -1,39 +1,18 @@
|
|
1
1
|
module Prezzo
|
2
2
|
module Explainable
|
3
|
-
def self.included(base)
|
4
|
-
base.class_eval do
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
module ClassMethods
|
10
|
-
def explain_with(*component_names, **options)
|
11
|
-
@explained_components ||= {}
|
12
|
-
component_names.each do |component_name|
|
13
|
-
@explained_components[component_name] = options
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
attr_reader :explained_components
|
18
|
-
end
|
19
|
-
|
20
3
|
def explain
|
21
|
-
explained_components = self.class.explained_components || {}
|
22
|
-
|
23
4
|
explanation = {
|
24
5
|
total: calculate,
|
25
|
-
components: {},
|
26
6
|
}
|
27
7
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
8
|
+
components = compile_components
|
9
|
+
explanation[:components] = components unless components.empty?
|
10
|
+
|
11
|
+
context = compile_params
|
12
|
+
explanation[:context] = context unless context.empty?
|
13
|
+
|
14
|
+
transients = compile_transients
|
15
|
+
explanation[:transients] = transients unless transients.empty?
|
37
16
|
|
38
17
|
explanation
|
39
18
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Prezzo
|
2
|
+
module ParamsDSL
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def param(name, options = {}, &block)
|
11
|
+
params << name
|
12
|
+
|
13
|
+
define_method(name) do
|
14
|
+
cached_params[name] ||=
|
15
|
+
begin
|
16
|
+
value = context.fetch(name, options[:default])
|
17
|
+
value.class.class_eval(&block) if block
|
18
|
+
value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def params
|
24
|
+
@params ||= []
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def compile_params
|
29
|
+
params = self.class.params.reduce({}) do |acc, name|
|
30
|
+
value = public_send(name)
|
31
|
+
value = value.compile_params if value.respond_to?(:compile_params)
|
32
|
+
acc[name] = value
|
33
|
+
acc
|
34
|
+
end
|
35
|
+
|
36
|
+
if @sub_context_name
|
37
|
+
{
|
38
|
+
@sub_context_name => params,
|
39
|
+
}
|
40
|
+
else
|
41
|
+
params
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def sub_context(name)
|
46
|
+
@sub_context_name = name
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def cached_params
|
52
|
+
@cached_params ||= {}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Prezzo
|
2
|
+
module TransientDSL
|
3
|
+
def self.included(base)
|
4
|
+
base.class_eval do
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ClassMethods
|
10
|
+
def transient(name)
|
11
|
+
transients << name
|
12
|
+
|
13
|
+
define_method(name) do
|
14
|
+
cached_transients[name] ||= yield
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def transients
|
19
|
+
@transients ||= []
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def compile_transients
|
24
|
+
self.class.transients.reduce({}) do |acc, name|
|
25
|
+
public_send(name) # force transient cache
|
26
|
+
acc[name] = cached_transients[name]
|
27
|
+
acc
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def cached_transients
|
34
|
+
@cached_transients ||= {}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/prezzo/version.rb
CHANGED
data/prezzo.gemspec
CHANGED
@@ -17,7 +17,6 @@ Gem::Specification.new do |spec|
|
|
17
17
|
end
|
18
18
|
spec.require_paths = ["lib"]
|
19
19
|
|
20
|
-
spec.add_dependency "hanami-validations", "~> 1.0"
|
21
20
|
spec.add_development_dependency "bundler", "~> 1.13"
|
22
21
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
22
|
spec.add_development_dependency "rspec", "~> 3.0"
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: prezzo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0.pre.rc
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcelo Boeira
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: hanami-validations
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '1.0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '1.0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: bundler
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -173,9 +159,11 @@ files:
|
|
173
159
|
- bin/setup
|
174
160
|
- lib/prezzo.rb
|
175
161
|
- lib/prezzo/calculator.rb
|
176
|
-
- lib/prezzo/
|
162
|
+
- lib/prezzo/components_dsl.rb
|
177
163
|
- lib/prezzo/context.rb
|
178
164
|
- lib/prezzo/explainable.rb
|
165
|
+
- lib/prezzo/params_dsl.rb
|
166
|
+
- lib/prezzo/transient_dsl.rb
|
179
167
|
- lib/prezzo/version.rb
|
180
168
|
- prezzo.gemspec
|
181
169
|
homepage: http://github.com/marceloboeira/prezzo
|
@@ -192,12 +180,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
192
180
|
version: '0'
|
193
181
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
194
182
|
requirements:
|
195
|
-
- - "
|
183
|
+
- - ">"
|
196
184
|
- !ruby/object:Gem::Version
|
197
|
-
version:
|
185
|
+
version: 1.3.1
|
198
186
|
requirements: []
|
199
187
|
rubyforge_project:
|
200
|
-
rubygems_version: 2.6.
|
188
|
+
rubygems_version: 2.6.8
|
201
189
|
signing_key:
|
202
190
|
specification_version: 4
|
203
191
|
summary: Toolbox to create complex pricing models
|
data/lib/prezzo/composable.rb
DELETED
@@ -1,33 +0,0 @@
|
|
1
|
-
module Prezzo
|
2
|
-
module Composable
|
3
|
-
def self.included(base)
|
4
|
-
base.class_eval do
|
5
|
-
base.extend(ClassMethods)
|
6
|
-
end
|
7
|
-
end
|
8
|
-
|
9
|
-
module ClassMethods
|
10
|
-
def composed_by(options)
|
11
|
-
options.each do |name, klass|
|
12
|
-
components << name
|
13
|
-
|
14
|
-
define_method(name) do
|
15
|
-
cached_components[name] ||= klass.new(context)
|
16
|
-
|
17
|
-
cached_components[name].calculate
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def components
|
23
|
-
@components ||= []
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def cached_components
|
30
|
-
@cached_components ||= {}
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|