sinclair 1.14.2 → 1.16.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 +1 -0
- data/README.md +11 -11
- data/config/yardstick.yml +11 -1
- data/lib/sinclair/caster/class_methods.rb +129 -0
- data/lib/sinclair/caster.rb +381 -0
- data/lib/sinclair/config_class.rb +4 -10
- data/lib/sinclair/method_definition/stringifier.rb +9 -7
- data/lib/sinclair/version.rb +1 -1
- data/lib/sinclair.rb +22 -21
- data/spec/integration/readme/sinclair/types_of_definition_spec.rb +8 -8
- data/spec/integration/yard/my_builder_spec.rb +8 -14
- data/spec/integration/yard/sinclair/add_method_spec.rb +11 -10
- data/spec/integration/yard/sinclair/caster/cast_spec.rb +57 -0
- data/spec/integration/yard/sinclair/caster/cast_with_spec.rb +54 -0
- data/spec/integration/yard/sinclair/caster/caster_for_spec.rb +16 -0
- data/spec/integration/yard/sinclair/caster/class_methods_spec.rb +23 -0
- data/spec/integration/yard/sinclair/config_builder_spec.rb +6 -8
- data/spec/integration/yard/sinclair/config_class_spec.rb +7 -21
- data/spec/integration/yard/sinclair_spec.rb +13 -32
- data/spec/lib/sinclair/caster/class_methods_spec.rb +208 -0
- data/spec/lib/sinclair/caster_spec.rb +75 -0
- data/spec/support/models/enum_caster.rb +6 -0
- data/spec/support/models/enum_converter.rb +27 -0
- data/spec/support/models/hash_model.rb +11 -0
- data/spec/support/models/hash_person.rb +11 -0
- data/spec/support/models/math_caster.rb +17 -0
- data/spec/support/models/ruby_string_caster.rb +14 -0
- data/spec/support/models/string_parser.rb +9 -0
- metadata +17 -2
@@ -0,0 +1,208 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::Caster::ClassMethods do
|
6
|
+
subject(:caster) { Class.new(superclass) }
|
7
|
+
|
8
|
+
let(:superclass) do
|
9
|
+
Class.new(Sinclair::Caster) do
|
10
|
+
cast_with(:string, :to_s)
|
11
|
+
cast_with(:integer, :to_i)
|
12
|
+
cast_with(:float, :to_f)
|
13
|
+
cast_with(String, :to_s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe '.cast_with' do
|
18
|
+
let(:value) { instance_double('value', to_p: final_value) }
|
19
|
+
let(:final_value) { Random.rand(100) }
|
20
|
+
|
21
|
+
context 'when a proc is given' do
|
22
|
+
it do
|
23
|
+
expect { caster.cast_with(:problem, &:to_p) }
|
24
|
+
.not_to raise_error
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when casting is called' do
|
28
|
+
before { caster.cast_with(:problem, &:to_p) }
|
29
|
+
|
30
|
+
it 'returns the cast value' do
|
31
|
+
expect(caster.cast(value, :problem)).to eq(final_value)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when a proc with two arguments is given' do
|
37
|
+
it do
|
38
|
+
expect { caster.cast_with(:problem) { |v, **_opts| v.to_p } }
|
39
|
+
.not_to raise_error
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when casting is called' do
|
43
|
+
before { caster.cast_with(:problem) { |v, sum:| v.to_p + sum } }
|
44
|
+
|
45
|
+
it 'returns the cast value' do
|
46
|
+
expect(caster.cast(value, :problem, sum: 2))
|
47
|
+
.to eq(final_value + 2)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when a symbol is given' do
|
53
|
+
let(:instance) { Sinclair::Caster.new(&:to_p) }
|
54
|
+
|
55
|
+
it do
|
56
|
+
expect { caster.cast_with(:problem, instance) }
|
57
|
+
.not_to raise_error
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'when casting is called' do
|
61
|
+
before { caster.cast_with(:problem, instance) }
|
62
|
+
|
63
|
+
it 'returns the cast value' do
|
64
|
+
expect(caster.cast(value, :problem)).to eq(final_value)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'when a caster is given is given' do
|
70
|
+
it do
|
71
|
+
expect { caster.cast_with(:problem, :to_p) }
|
72
|
+
.not_to raise_error
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when casting is called' do
|
76
|
+
before { caster.cast_with(:problem, :to_p) }
|
77
|
+
|
78
|
+
it 'returns the cast value' do
|
79
|
+
expect(caster.cast(value, :problem)).to eq(final_value)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when key is a class' do
|
85
|
+
it do
|
86
|
+
expect { caster.cast_with(Integer, :to_i) }
|
87
|
+
.not_to raise_error
|
88
|
+
end
|
89
|
+
|
90
|
+
context 'when casting is called' do
|
91
|
+
before { caster.cast_with(Integer, :to_i) }
|
92
|
+
|
93
|
+
it 'returns the cast value' do
|
94
|
+
expect(caster.cast('10', Integer)).to eq(10)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context 'when key is a module' do
|
100
|
+
it do
|
101
|
+
expect { caster.cast_with(JSON) { |value| JSON.parse(value) } }
|
102
|
+
.not_to raise_error
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'when casting is called' do
|
106
|
+
before { caster.cast_with(JSON) { |value| JSON.parse(value) } }
|
107
|
+
|
108
|
+
it 'returns the cast value' do
|
109
|
+
expect(caster.cast('{"key":"value"}', JSON))
|
110
|
+
.to eq({ 'key' => 'value' })
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'when key is a superclass' do
|
116
|
+
it do
|
117
|
+
expect { caster.cast_with(Numeric, :to_i) }
|
118
|
+
.not_to raise_error
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when casting is called with the child class' do
|
122
|
+
before { caster.cast_with(Numeric, :to_i) }
|
123
|
+
|
124
|
+
it 'returns the cast value' do
|
125
|
+
expect(caster.cast('10', Integer)).to eq(10)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
describe '.caster_for' do
|
132
|
+
context 'when nil key is given' do
|
133
|
+
let(:value) { values.sample }
|
134
|
+
let(:values) do
|
135
|
+
[Random.rand, 'some string', { key: 10 }, Object.new, Class.new, [2, 3]]
|
136
|
+
end
|
137
|
+
|
138
|
+
it { expect(caster.caster_for(nil)).to be_a(Sinclair::Caster) }
|
139
|
+
|
140
|
+
it 'returns the default caster' do
|
141
|
+
expect(caster.caster_for(nil).cast(value)).to eq(value)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
context 'when the key has been defined with a symbol key' do
|
146
|
+
before { caster.cast_with(:problem, :to_p) }
|
147
|
+
|
148
|
+
it do
|
149
|
+
expect(caster.caster_for(:problem))
|
150
|
+
.to be_a(Sinclair::Caster)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'when the key has not been defined' do
|
155
|
+
it do
|
156
|
+
expect(caster.caster_for(:problem))
|
157
|
+
.to be_a(Sinclair::Caster)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe '.cast' do
|
163
|
+
let(:value) { values.sample }
|
164
|
+
let(:values) do
|
165
|
+
[Random.rand, 'some string', { key: 10 }, Object.new, Class.new, [2, 3]]
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'when klass is nil' do
|
169
|
+
it 'returns the value' do
|
170
|
+
expect(caster.cast(value, nil))
|
171
|
+
.to eq(value)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
context 'when class is :string' do
|
176
|
+
it 'returns the value as string' do
|
177
|
+
expect(caster.cast(value, :string))
|
178
|
+
.to eq(value.to_s)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context 'when class is :integer' do
|
183
|
+
let(:value) { '10.5' }
|
184
|
+
|
185
|
+
it 'returns the value as integer' do
|
186
|
+
expect(caster.cast(value, :integer))
|
187
|
+
.to eq(10)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context 'when class is :float' do
|
192
|
+
let(:value) { '10.5' }
|
193
|
+
|
194
|
+
it 'returns the value as float' do
|
195
|
+
expect(caster.cast(value, :float))
|
196
|
+
.to eq(10.5)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
describe '.master_caster!' do
|
202
|
+
it 'ignores superclass registered casters' do
|
203
|
+
expect { caster.master_caster! }
|
204
|
+
.to change { caster.cast('10', :integer) }
|
205
|
+
.from(10).to('10')
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Sinclair::Caster do
|
6
|
+
subject(:caster) { caster_class.new(&method_name) }
|
7
|
+
|
8
|
+
let(:caster_class) { Class.new(described_class) }
|
9
|
+
|
10
|
+
describe '.cast' do
|
11
|
+
context 'when no options are given and the block accepts none' do
|
12
|
+
let(:method_name) { :to_s }
|
13
|
+
|
14
|
+
it 'uses the block to transform the value' do
|
15
|
+
expect(caster.cast(10)).to eq('10')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'when options are given and the block accepts none' do
|
20
|
+
let(:method_name) { :to_i }
|
21
|
+
|
22
|
+
it 'uses the block to transform the value' do
|
23
|
+
expect(caster.cast('10', extra: true)).to eq(10)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when no options are given and the block accepts options' do
|
28
|
+
subject(:caster) do
|
29
|
+
caster_class.new do |value, sum: 5|
|
30
|
+
(value.to_i + sum).to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'uses the block to transform the value' do
|
35
|
+
expect(caster.cast('10')).to eq('15')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'when options are given and the block accepts options' do
|
40
|
+
subject(:caster) do
|
41
|
+
caster_class.new do |value, sum:|
|
42
|
+
(value.to_i + sum).to_s
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'uses the options in the block' do
|
47
|
+
expect(caster.cast('10', sum: 5)).to eq('15')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when no options are given and the block requires options' do
|
52
|
+
subject(:caster) do
|
53
|
+
caster_class.new do |value, sum:|
|
54
|
+
(value.to_i + sum).to_s
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it do
|
59
|
+
expect { caster.cast('10') }.to raise_error(ArgumentError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when extra options are given and the block accepts options' do
|
64
|
+
subject(:caster) do
|
65
|
+
caster_class.new do |value, sum:|
|
66
|
+
(value.to_i + sum).to_s
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'ignores extra options' do
|
71
|
+
expect(caster.cast('10', sum: 5, extra: true)).to eq('15')
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: false
|
2
|
+
|
3
|
+
module EnumConverter
|
4
|
+
class << self
|
5
|
+
def to_hash(value)
|
6
|
+
return value if value.is_a?(Hash)
|
7
|
+
|
8
|
+
hash_caster.cast(value)
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_array(value)
|
12
|
+
return value if value.is_a?(Array)
|
13
|
+
|
14
|
+
array_caster.cast(value)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def hash_caster
|
20
|
+
@hash_caster ||= EnumCaster.caster_for(:hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
def array_caster
|
24
|
+
@array_caster ||= EnumCaster.caster_for(:array)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class MathCaster < Sinclair::Caster
|
4
|
+
cast_with(:float, :to_f)
|
5
|
+
|
6
|
+
cast_with(:log) do |value, base: 10|
|
7
|
+
value = MathCaster.cast(value, :float)
|
8
|
+
|
9
|
+
Math.log(value, base)
|
10
|
+
end
|
11
|
+
|
12
|
+
cast_with(:exp) do |value, base: 10|
|
13
|
+
value = MathCaster.cast(value, :float)
|
14
|
+
|
15
|
+
base**value
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class RubyStringCaster < Sinclair::Caster
|
4
|
+
master_caster!
|
5
|
+
|
6
|
+
cast_with(NilClass) { 'nil' }
|
7
|
+
cast_with(Symbol) { |value| ":#{value}" }
|
8
|
+
cast_with(String, :to_json)
|
9
|
+
cast_with(Object, :to_s)
|
10
|
+
|
11
|
+
def self.to_ruby_string(value)
|
12
|
+
cast(value, value.class)
|
13
|
+
end
|
14
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinclair
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- DarthJee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -273,6 +273,8 @@ files:
|
|
273
273
|
- config/yardstick.yml
|
274
274
|
- docker-compose.yml
|
275
275
|
- lib/sinclair.rb
|
276
|
+
- lib/sinclair/caster.rb
|
277
|
+
- lib/sinclair/caster/class_methods.rb
|
276
278
|
- lib/sinclair/class_methods.rb
|
277
279
|
- lib/sinclair/comparable.rb
|
278
280
|
- lib/sinclair/comparable/class_methods.rb
|
@@ -339,6 +341,10 @@ files:
|
|
339
341
|
- spec/integration/yard/my_builder_spec.rb
|
340
342
|
- spec/integration/yard/sinclair/add_class_method_spec.rb
|
341
343
|
- spec/integration/yard/sinclair/add_method_spec.rb
|
344
|
+
- spec/integration/yard/sinclair/caster/cast_spec.rb
|
345
|
+
- spec/integration/yard/sinclair/caster/cast_with_spec.rb
|
346
|
+
- spec/integration/yard/sinclair/caster/caster_for_spec.rb
|
347
|
+
- spec/integration/yard/sinclair/caster/class_methods_spec.rb
|
342
348
|
- spec/integration/yard/sinclair/class_methods/build_spec.rb
|
343
349
|
- spec/integration/yard/sinclair/comparable_spec.rb
|
344
350
|
- spec/integration/yard/sinclair/config_builder_spec.rb
|
@@ -361,6 +367,8 @@ files:
|
|
361
367
|
- spec/integration/yard/sinclair/options_parser_spec.rb
|
362
368
|
- spec/integration/yard/sinclair/options_spec.rb
|
363
369
|
- spec/integration/yard/sinclair_spec.rb
|
370
|
+
- spec/lib/sinclair/caster/class_methods_spec.rb
|
371
|
+
- spec/lib/sinclair/caster_spec.rb
|
364
372
|
- spec/lib/sinclair/class_methods_spec.rb
|
365
373
|
- spec/lib/sinclair/comparable_spec.rb
|
366
374
|
- spec/lib/sinclair/config/methods_builder_spec.rb
|
@@ -420,7 +428,11 @@ files:
|
|
420
428
|
- spec/support/models/dummy_config.rb
|
421
429
|
- spec/support/models/dummy_configurable.rb
|
422
430
|
- spec/support/models/dummy_options_parser.rb
|
431
|
+
- spec/support/models/enum_caster.rb
|
432
|
+
- spec/support/models/enum_converter.rb
|
423
433
|
- spec/support/models/env_settings.rb
|
434
|
+
- spec/support/models/hash_model.rb
|
435
|
+
- spec/support/models/hash_person.rb
|
424
436
|
- spec/support/models/host_config.rb
|
425
437
|
- spec/support/models/http_json_model.rb
|
426
438
|
- spec/support/models/http_person.rb
|
@@ -429,6 +441,7 @@ files:
|
|
429
441
|
- spec/support/models/job.rb
|
430
442
|
- spec/support/models/login_config.rb
|
431
443
|
- spec/support/models/login_configurable.rb
|
444
|
+
- spec/support/models/math_caster.rb
|
432
445
|
- spec/support/models/my_app_client.rb
|
433
446
|
- spec/support/models/my_builder.rb
|
434
447
|
- spec/support/models/my_class.rb
|
@@ -441,9 +454,11 @@ files:
|
|
441
454
|
- spec/support/models/person.rb
|
442
455
|
- spec/support/models/purchase.rb
|
443
456
|
- spec/support/models/random_generator.rb
|
457
|
+
- spec/support/models/ruby_string_caster.rb
|
444
458
|
- spec/support/models/server.rb
|
445
459
|
- spec/support/models/server_config.rb
|
446
460
|
- spec/support/models/service_client.rb
|
461
|
+
- spec/support/models/string_parser.rb
|
447
462
|
- spec/support/models/tv.rb
|
448
463
|
- spec/support/models/validator_builder.rb
|
449
464
|
- spec/support/sample_model.rb
|