ree_lib 1.0.36 → 1.0.38
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/Gemfile.lock +9 -2
- data/lib/ree_lib/Packages.schema.json +8 -0
- data/lib/ree_lib/packages/ree_actions/.gitignore +0 -0
- data/lib/ree_lib/packages/ree_actions/.rspec +2 -0
- data/lib/ree_lib/packages/ree_actions/Package.schema.json +20 -0
- data/lib/ree_lib/packages/ree_actions/bin/console +5 -0
- data/lib/ree_lib/packages/ree_actions/package/ree_actions/action.rb +10 -0
- data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_builder.rb +65 -0
- data/lib/ree_lib/packages/ree_actions/package/ree_actions/action_dsl.rb +60 -0
- data/lib/ree_lib/packages/ree_actions/package/ree_actions/dsl.rb +102 -0
- data/lib/ree_lib/packages/ree_actions/package/ree_actions.rb +12 -0
- data/lib/ree_lib/packages/ree_actions/spec/package_schema_spec.rb +14 -0
- data/lib/ree_lib/packages/ree_actions/spec/ree_actions/action_dsl_spec.rb +62 -0
- data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +93 -0
- data/lib/ree_lib/packages/ree_actions/spec/spec_helper.rb +3 -0
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/functions/build_mapper_factory.rb +4 -0
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +17 -10
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory.rb +73 -35
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +23 -0
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/abstract_wrapper.rb +8 -0
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/{types → wrappers}/array.rb +10 -17
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper.rb +5 -1
- data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +62 -2
- data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/any_spec.rb +47 -0
- data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/type_options_spec.rb +4 -4
- data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/{types → wrappers}/array_spec.rb +7 -7
- data/lib/ree_lib/packages/ree_roda/.gitignore +0 -0
- data/lib/ree_lib/packages/ree_roda/.rspec +2 -0
- data/lib/ree_lib/packages/ree_roda/Package.schema.json +58 -0
- data/lib/ree_lib/packages/ree_roda/bin/console +5 -0
- data/lib/ree_lib/packages/ree_roda/package/ree_roda/app.rb +46 -0
- data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_actions.rb +150 -0
- data/lib/ree_lib/packages/ree_roda/package/ree_roda/plugins/ree_logger.rb +66 -0
- data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_action_errors.rb +76 -0
- data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/build_swagger_from_actions.rb +55 -0
- data/lib/ree_lib/packages/ree_roda/package/ree_roda/services/status_from_error.rb +25 -0
- data/lib/ree_lib/packages/ree_roda/package/ree_roda.rb +19 -0
- data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json +28 -0
- data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json +63 -0
- data/lib/ree_lib/packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json +28 -0
- data/lib/ree_lib/packages/ree_roda/spec/package_schema_spec.rb +14 -0
- data/lib/ree_lib/packages/ree_roda/spec/ree_roda/app_spec.rb +84 -0
- data/lib/ree_lib/packages/ree_roda/spec/spec_helper.rb +3 -0
- data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/beans/type_definitions_repo.rb +1 -1
- data/lib/ree_lib/packages/ree_swagger/spec/functions/build_parameters_spec.rb +1 -1
- data/lib/ree_lib/packages/ree_swagger/spec/functions/build_serializer_schema_spec.rb +3 -3
- data/lib/ree_lib/version.rb +1 -1
- metadata +65 -4
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
class ReeMapper::MapperFactory
|
4
4
|
class << self
|
5
|
-
attr_reader :types, :strategies
|
5
|
+
attr_reader :types, :strategies, :wrappers
|
6
6
|
end
|
7
7
|
|
8
8
|
contract(Symbol => Nilor[ReeMapper::MapperStrategy])
|
@@ -18,9 +18,9 @@ class ReeMapper::MapperFactory
|
|
18
18
|
)
|
19
19
|
end
|
20
20
|
|
21
|
-
contract(Symbol, ReeMapper::Mapper =>
|
21
|
+
contract(Symbol, ReeMapper::Mapper => SubclassOf[self]).throws(ArgumentError)
|
22
22
|
def self.register_mapper(name, type)
|
23
|
-
raise ArgumentError, "
|
23
|
+
raise ArgumentError, "mapper registration name should not end with `?`" if name.to_s.end_with?('?')
|
24
24
|
|
25
25
|
defined_strategy_method = types[name]&.flat_map(&:strategy_methods)&.detect { type.find_strategy(_1) }
|
26
26
|
raise ArgumentError, "type :#{name} with `#{defined_strategy_method}` strategy already registered" if defined_strategy_method
|
@@ -35,7 +35,7 @@ class ReeMapper::MapperFactory
|
|
35
35
|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
36
36
|
def #{name}(field_name = nil, optional: false, **opts)
|
37
37
|
raise ReeMapper::Error, "invalid DSL usage" unless @mapper
|
38
|
-
raise ArgumentError, "
|
38
|
+
raise ArgumentError, "wrapped item can't be optional" if field_name.nil? && optional
|
39
39
|
|
40
40
|
type = self.class.types.fetch(:#{name}).detect { (@mapper.strategy_methods - _1.strategy_methods).empty? }
|
41
41
|
|
@@ -43,9 +43,11 @@ class ReeMapper::MapperFactory
|
|
43
43
|
raise ReeMapper::UnsupportedTypeError, "type :#{name} should implement `\#{@mapper.strategy_methods.join(', ')}`"
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
field = ReeMapper::Field.new(type, field_name, optional: optional, **opts)
|
47
47
|
|
48
|
-
|
48
|
+
return field unless field_name
|
49
|
+
|
50
|
+
@mapper.add_field(field)
|
49
51
|
end
|
50
52
|
|
51
53
|
def #{name}?(field_name, **opts)
|
@@ -56,6 +58,68 @@ class ReeMapper::MapperFactory
|
|
56
58
|
self
|
57
59
|
end
|
58
60
|
|
61
|
+
contract(Symbol, SubclassOf[ReeMapper::AbstractWrapper] => SubclassOf[self])
|
62
|
+
def self.register_wrapper(name, wrapper)
|
63
|
+
raise ArgumentError, "wrapper registration name should not end with `?`" if name.to_s.end_with?('?')
|
64
|
+
raise ArgumentError, "method :#{name} already defined" if !wrappers.key?(name) && method_defined?(name)
|
65
|
+
|
66
|
+
wrappers[name] ||= []
|
67
|
+
wrappers[name] << wrapper
|
68
|
+
|
69
|
+
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
|
70
|
+
contract(
|
71
|
+
Nilor[Symbol, ReeMapper::Field],
|
72
|
+
Nilor[ReeMapper::Field],
|
73
|
+
Kwargs[optional: Bool, dto: Nilor[Class]],
|
74
|
+
Ksplat[RestKeys => Any],
|
75
|
+
Optblock => Nilor[ReeMapper::Field]
|
76
|
+
).throws(ReeMapper::Error, ArgumentError, ReeMapper::UnsupportedTypeError)
|
77
|
+
def #{name}(field_name = nil, subject = nil, optional: false, dto: nil, **opts, &blk)
|
78
|
+
raise ReeMapper::Error, "invalid DSL usage" unless @mapper
|
79
|
+
raise ArgumentError, 'wrapped type does not permit :dto without :block' if dto && !blk
|
80
|
+
|
81
|
+
if field_name.is_a?(ReeMapper::Field)
|
82
|
+
raise ArgumentError, "field_name should be a Symbol" if subject
|
83
|
+
|
84
|
+
subject = field_name
|
85
|
+
field_name = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
raise ArgumentError, "wrapped item can't be optional" if field_name.nil? && optional
|
89
|
+
raise ArgumentError, "wrapped type should use either :subject or :block" if subject && blk || !subject && !blk
|
90
|
+
|
91
|
+
if blk
|
92
|
+
subject = ReeMapper::Field.new(
|
93
|
+
hash_from_blk(dto: dto, &blk)
|
94
|
+
)
|
95
|
+
end
|
96
|
+
|
97
|
+
wrapper = self.class.wrappers.fetch(:#{name}).detect do |wrapper|
|
98
|
+
@mapper.strategy_methods.all? { wrapper.method_defined?(_1) }
|
99
|
+
end
|
100
|
+
|
101
|
+
unless wrapper
|
102
|
+
raise ReeMapper::UnsupportedTypeError, "wrapper :#{name} should implement `\#{@mapper.strategy_methods.join(', ')}`"
|
103
|
+
end
|
104
|
+
|
105
|
+
type = ReeMapper::Mapper.build(@mapper.strategies, wrapper.new(subject))
|
106
|
+
type.name = :#{name}
|
107
|
+
|
108
|
+
field = ReeMapper::Field.new(type, field_name, optional: optional, **opts)
|
109
|
+
|
110
|
+
return field unless field_name
|
111
|
+
|
112
|
+
@mapper.add_field(field)
|
113
|
+
end
|
114
|
+
|
115
|
+
def #{name}?(*args, **opts, &blk)
|
116
|
+
#{name}(*args, optional: true, **opts, &blk)
|
117
|
+
end
|
118
|
+
RUBY
|
119
|
+
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
59
123
|
contract(
|
60
124
|
Kwargs[
|
61
125
|
register_as: Nilor[Symbol]
|
@@ -71,41 +135,15 @@ class ReeMapper::MapperFactory
|
|
71
135
|
@mapper = mapper
|
72
136
|
end
|
73
137
|
|
74
|
-
contract(Nilor[Symbol], Kwargs[each: Nilor[ReeMapper::Field], optional: Bool, dto: Nilor[Class]], Ksplat[RestKeys => Any], Optblock => Nilor[ReeMapper::Field])
|
75
|
-
def array(field_name = nil, each: nil, optional: false, dto: nil, **opts, &blk)
|
76
|
-
raise ReeMapper::Error, "invalid DSL usage" unless @mapper
|
77
|
-
raise ArgumentError, "array item can't be optional" if field_name.nil? && optional
|
78
|
-
raise ArgumentError, 'array type should use either :each or :block' if each && blk || !each && !blk
|
79
|
-
raise ArgumentError, 'array does not permit :dto without :block' if dto && !blk
|
80
|
-
raise ArgumentError, 'array does not permit :only and :except keys' if opts.key?(:only) || opts.key?(:except)
|
81
|
-
|
82
|
-
if blk
|
83
|
-
each = ReeMapper::Field.new(
|
84
|
-
hash_from_blk(dto: dto, &blk)
|
85
|
-
)
|
86
|
-
end
|
87
|
-
|
88
|
-
type = ReeMapper::Mapper.build(@mapper.strategies, ReeMapper::Array.new(each))
|
89
|
-
|
90
|
-
return ReeMapper::Field.new(type, optional: optional, **opts) unless field_name
|
91
|
-
|
92
|
-
@mapper.add_field(type, field_name, optional: optional, **opts)
|
93
|
-
end
|
94
|
-
|
95
|
-
contract(Symbol, Kwargs[each: Nilor[ReeMapper::Field]], Ksplat[RestKeys => Any], Optblock => Nilor[ReeMapper::Field])
|
96
|
-
def array?(field_name, each: nil, **opts, &blk)
|
97
|
-
raise ArgumentError if opts.key?(:optional)
|
98
|
-
|
99
|
-
array(field_name, each: each, optional: true, **opts, &blk)
|
100
|
-
end
|
101
|
-
|
102
138
|
contract(Symbol, Kwargs[dto: Nilor[Class]], Ksplat[RestKeys => Any], Block => nil)
|
103
139
|
def hash(field_name, dto: nil, **opts, &blk)
|
104
140
|
raise ReeMapper::Error, "invalid DSL usage" unless @mapper
|
105
141
|
|
106
142
|
type = hash_from_blk(dto: dto, &blk)
|
107
143
|
|
108
|
-
|
144
|
+
field = ReeMapper::Field.new(type, field_name, **opts)
|
145
|
+
|
146
|
+
@mapper.add_field(field)
|
109
147
|
end
|
110
148
|
|
111
149
|
contract(Symbol, Ksplat[RestKeys => Any], Block => nil)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ReeMapper::Any < ReeMapper::AbstractType
|
4
|
+
contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
|
5
|
+
def serialize(value, name:, role: nil)
|
6
|
+
value
|
7
|
+
end
|
8
|
+
|
9
|
+
contract(Any , Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
|
10
|
+
def cast(value, name:, role: nil)
|
11
|
+
value
|
12
|
+
end
|
13
|
+
|
14
|
+
contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
|
15
|
+
def db_dump(value, name:, role: nil)
|
16
|
+
value
|
17
|
+
end
|
18
|
+
|
19
|
+
contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
|
20
|
+
def db_load(value, name:, role: nil)
|
21
|
+
value
|
22
|
+
end
|
23
|
+
end
|
@@ -1,22 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
class ReeMapper::Array < ReeMapper::
|
4
|
-
attr_reader :of
|
5
|
-
|
6
|
-
contract ReeMapper::Field => Any
|
7
|
-
def initialize(of)
|
8
|
-
@of = of
|
9
|
-
end
|
10
|
-
|
3
|
+
class ReeMapper::Array < ReeMapper::AbstractWrapper
|
11
4
|
contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]], fields_filters: ArrayOf[ReeMapper::FieldsFilter]] => Array)
|
12
5
|
.throws(ReeMapper::TypeError)
|
13
6
|
def serialize(value, name:, role: nil, fields_filters: [])
|
14
7
|
if value.is_a?(Array)
|
15
8
|
value.map.with_index {
|
16
|
-
if _1.nil? &&
|
9
|
+
if _1.nil? && subject.null
|
17
10
|
_1
|
18
11
|
else
|
19
|
-
|
12
|
+
subject.type.serialize(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
|
20
13
|
end
|
21
14
|
}
|
22
15
|
else
|
@@ -29,10 +22,10 @@ class ReeMapper::Array < ReeMapper::AbstractType
|
|
29
22
|
def cast(value, name:, role: nil, fields_filters: [])
|
30
23
|
if value.is_a?(Array)
|
31
24
|
value.map.with_index {
|
32
|
-
if _1.nil? &&
|
25
|
+
if _1.nil? && subject.null
|
33
26
|
_1
|
34
27
|
else
|
35
|
-
|
28
|
+
subject.type.cast(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
|
36
29
|
end
|
37
30
|
}
|
38
31
|
else
|
@@ -45,10 +38,10 @@ class ReeMapper::Array < ReeMapper::AbstractType
|
|
45
38
|
def db_dump(value, name:, role: nil, fields_filters: [])
|
46
39
|
if value.is_a?(Array)
|
47
40
|
value.map.with_index {
|
48
|
-
if _1.nil? &&
|
41
|
+
if _1.nil? && subject.null
|
49
42
|
_1
|
50
43
|
else
|
51
|
-
|
44
|
+
subject.type.db_dump(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
|
52
45
|
end
|
53
46
|
}
|
54
47
|
else
|
@@ -61,14 +54,14 @@ class ReeMapper::Array < ReeMapper::AbstractType
|
|
61
54
|
def db_load(value, name:, role: nil, fields_filters: [])
|
62
55
|
if value.is_a?(Array)
|
63
56
|
value.map.with_index {
|
64
|
-
if _1.nil? &&
|
57
|
+
if _1.nil? && subject.null
|
65
58
|
_1
|
66
59
|
else
|
67
|
-
|
60
|
+
subject.type.db_load(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
|
68
61
|
end
|
69
62
|
}
|
70
63
|
else
|
71
64
|
raise ReeMapper::TypeError, "`#{name}` should be an array"
|
72
65
|
end
|
73
66
|
end
|
74
|
-
end
|
67
|
+
end
|
@@ -22,14 +22,18 @@ module ReeMapper
|
|
22
22
|
require_relative 'ree_mapper/fields_filter'
|
23
23
|
require_relative 'ree_mapper/field'
|
24
24
|
|
25
|
+
|
26
|
+
require_relative 'ree_mapper/wrappers/abstract_wrapper'
|
27
|
+
require_relative 'ree_mapper/wrappers/array'
|
28
|
+
|
25
29
|
require_relative 'ree_mapper/types/bool'
|
30
|
+
require_relative 'ree_mapper/types/any'
|
26
31
|
require_relative 'ree_mapper/types/date_time'
|
27
32
|
require_relative 'ree_mapper/types/time'
|
28
33
|
require_relative 'ree_mapper/types/date'
|
29
34
|
require_relative 'ree_mapper/types/float'
|
30
35
|
require_relative 'ree_mapper/types/integer'
|
31
36
|
require_relative 'ree_mapper/types/string'
|
32
|
-
require_relative 'ree_mapper/types/array'
|
33
37
|
|
34
38
|
require_relative 'ree_mapper/strategy_outputs/strategy_output'
|
35
39
|
require_relative 'ree_mapper/strategy_outputs/object_output'
|
@@ -43,7 +43,7 @@ RSpec.describe ReeMapper::MapperFactory do
|
|
43
43
|
).to eq({ val: { id: 1 } })
|
44
44
|
}
|
45
45
|
|
46
|
-
it 'allow to register caster and serializer with same name' do
|
46
|
+
it 'allow to register caster and serializer with the same name' do
|
47
47
|
caster = mapper_factory.call.use(:cast) { string :name }
|
48
48
|
|
49
49
|
mapper_factory.register_mapper(:new_type, serializer)
|
@@ -69,7 +69,7 @@ RSpec.describe ReeMapper::MapperFactory do
|
|
69
69
|
it 'raise an error if the mapper name is ended by ?' do
|
70
70
|
expect {
|
71
71
|
mapper_factory.register_mapper(:new_type?, serializer)
|
72
|
-
}.to raise_error(ArgumentError, '
|
72
|
+
}.to raise_error(ArgumentError, 'mapper registration name should not end with `?`')
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'raise an error if the mapper name is reserved' do
|
@@ -79,6 +79,66 @@ RSpec.describe ReeMapper::MapperFactory do
|
|
79
79
|
end
|
80
80
|
end
|
81
81
|
|
82
|
+
describe '.register_wrapper' do
|
83
|
+
let(:round_wrapper) {
|
84
|
+
Class.new(ReeMapper::AbstractWrapper) do
|
85
|
+
def serialize(value, name:, **opts)
|
86
|
+
raise ReeMapper::TypeError, "`#{name}` should be a number" if !value.is_a?(Numeric)
|
87
|
+
|
88
|
+
subject.type.serialize(value.round, name: name, **opts)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
}
|
92
|
+
|
93
|
+
it {
|
94
|
+
mapper_factory.register_wrapper(:round, round_wrapper)
|
95
|
+
|
96
|
+
expect(
|
97
|
+
mapper_factory.call.use(:serialize) { round :val, integer }.serialize({ val: 1.1 })
|
98
|
+
).to eq({ val: 1 })
|
99
|
+
}
|
100
|
+
|
101
|
+
it 'allow to register caster and serializer with the same name' do
|
102
|
+
caster_round_wrapper = Class.new(ReeMapper::AbstractWrapper) do
|
103
|
+
def cast(value, name:, **opts)
|
104
|
+
value = subject.type.cast(value, name: name, **opts)
|
105
|
+
|
106
|
+
raise ReeMapper::TypeError, "`#{name}` should be a number" if !value.is_a?(Numeric)
|
107
|
+
value.round
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
mapper_factory.register_wrapper(:round, round_wrapper)
|
112
|
+
mapper_factory.register_wrapper(:round, caster_round_wrapper)
|
113
|
+
|
114
|
+
expect(
|
115
|
+
mapper_factory.call.use(:serialize) { round :val, integer }.serialize({ val: 1.1 })
|
116
|
+
).to eq({ val: 1 })
|
117
|
+
|
118
|
+
expect(
|
119
|
+
mapper_factory.call.use(:cast) { round :val, float }.cast({ val: '1.1' })
|
120
|
+
).to eq({ val: 1 })
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'raise an error if the registration wrapper name is ended by ?' do
|
124
|
+
expect {
|
125
|
+
mapper_factory.register_wrapper(:new_type?, round_wrapper)
|
126
|
+
}.to raise_error(ArgumentError, 'wrapper registration name should not end with `?`')
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'raise an error if name is reserved' do
|
130
|
+
expect {
|
131
|
+
mapper_factory.register_wrapper(:hash, round_wrapper)
|
132
|
+
}.to raise_error(ArgumentError, 'method :hash already defined')
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'raise an error if name is reserved by mapper' do
|
136
|
+
expect {
|
137
|
+
mapper_factory.register_wrapper(:integer, round_wrapper)
|
138
|
+
}.to raise_error(ArgumentError, 'method :integer already defined')
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
82
142
|
describe '.use' do
|
83
143
|
it {
|
84
144
|
mapper = mapper_factory.call.use(:cast) do
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe 'ReeMapper::Bool' do
|
4
|
+
link :build_mapper_factory, from: :ree_mapper
|
5
|
+
link :build_mapper_strategy, from: :ree_mapper
|
6
|
+
|
7
|
+
let(:mapper_factory) {
|
8
|
+
build_mapper_factory(
|
9
|
+
strategies: [
|
10
|
+
build_mapper_strategy(method: :cast, dto: Hash),
|
11
|
+
build_mapper_strategy(method: :serialize, dto: Hash),
|
12
|
+
build_mapper_strategy(method: :db_dump, dto: Hash),
|
13
|
+
build_mapper_strategy(method: :db_load, dto: Hash)
|
14
|
+
]
|
15
|
+
)
|
16
|
+
}
|
17
|
+
|
18
|
+
let(:mapper) {
|
19
|
+
mapper_factory.call.use(:cast).use(:serialize).use(:db_dump).use(:db_load) {
|
20
|
+
any :any
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
describe '#serialize' do
|
25
|
+
it {
|
26
|
+
expect(mapper.serialize({ any: true })).to eq({ any: true })
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#cast' do
|
31
|
+
it {
|
32
|
+
expect(mapper.cast({ 'any' => true })).to eq({ any: true })
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#db_dump' do
|
37
|
+
it {
|
38
|
+
expect(mapper.db_dump(OpenStruct.new({ any: true }))).to eq({ any: true })
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#db_load' do
|
43
|
+
it {
|
44
|
+
expect(mapper.db_load({ 'any' => true })).to eq({ any: true })
|
45
|
+
}
|
46
|
+
end
|
47
|
+
end
|
@@ -21,7 +21,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
|
|
21
21
|
integer :x
|
22
22
|
integer :y
|
23
23
|
integer :z
|
24
|
-
}
|
24
|
+
}
|
25
25
|
}
|
26
26
|
|
27
27
|
context 'with only' do
|
@@ -71,7 +71,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
|
|
71
71
|
point :y, except: [:x, :z]
|
72
72
|
end
|
73
73
|
|
74
|
-
array :points,
|
74
|
+
array :points, point(only: [:x, :y])
|
75
75
|
}
|
76
76
|
}
|
77
77
|
|
@@ -169,7 +169,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
|
|
169
169
|
integer :number
|
170
170
|
integer? :opt_number
|
171
171
|
integer :opt_number_long, optional: true
|
172
|
-
array? :opt_array,
|
172
|
+
array? :opt_array, integer
|
173
173
|
array? :opt_array_with_blk do
|
174
174
|
integer :id
|
175
175
|
end
|
@@ -278,7 +278,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
|
|
278
278
|
integer :for_all
|
279
279
|
integer :for_admin, role: :admin
|
280
280
|
}
|
281
|
-
|
281
|
+
|
282
282
|
mapper_factory.call.use(:cast) {
|
283
283
|
nested_type :my_field
|
284
284
|
}
|
@@ -17,8 +17,8 @@ RSpec.describe 'ReeMapper::Array' do
|
|
17
17
|
|
18
18
|
let(:mapper) {
|
19
19
|
mapper_factory.call.use(:cast).use(:serialize).use(:db_dump).use(:db_load) {
|
20
|
-
array :tags,
|
21
|
-
array? :ary_of_ary,
|
20
|
+
array :tags, integer
|
21
|
+
array? :ary_of_ary, array(integer)
|
22
22
|
}
|
23
23
|
}
|
24
24
|
|
@@ -73,7 +73,7 @@ RSpec.describe 'ReeMapper::Array' do
|
|
73
73
|
context 'with array of array' do
|
74
74
|
let(:mapper) {
|
75
75
|
mapper_factory.call.use(:serialize) {
|
76
|
-
array :coords,
|
76
|
+
array :coords, array(integer)
|
77
77
|
}
|
78
78
|
}
|
79
79
|
|
@@ -85,7 +85,7 @@ RSpec.describe 'ReeMapper::Array' do
|
|
85
85
|
context 'with nullable element of array' do
|
86
86
|
let(:mapper) {
|
87
87
|
mapper_factory.call.use(:serialize) {
|
88
|
-
array :tags,
|
88
|
+
array :tags, integer(null: true)
|
89
89
|
}
|
90
90
|
}
|
91
91
|
|
@@ -98,7 +98,7 @@ RSpec.describe 'ReeMapper::Array' do
|
|
98
98
|
it {
|
99
99
|
expect {
|
100
100
|
mapper_factory.call.use(:serialize) {
|
101
|
-
array :tags,
|
101
|
+
array :tags, integer?
|
102
102
|
}
|
103
103
|
}.to raise_error(ArgumentError)
|
104
104
|
}
|
@@ -106,7 +106,7 @@ RSpec.describe 'ReeMapper::Array' do
|
|
106
106
|
it {
|
107
107
|
expect {
|
108
108
|
mapper_factory.call.use(:serialize) {
|
109
|
-
array :tags,
|
109
|
+
array :tags, integer(optional: true)
|
110
110
|
}
|
111
111
|
}.to raise_error(ArgumentError)
|
112
112
|
}
|
@@ -114,7 +114,7 @@ RSpec.describe 'ReeMapper::Array' do
|
|
114
114
|
it {
|
115
115
|
expect {
|
116
116
|
mapper_factory.call.use(:serialize) {
|
117
|
-
array :tags,
|
117
|
+
array :tags, array(integer, optional: true)
|
118
118
|
}
|
119
119
|
}.to raise_error(ArgumentError)
|
120
120
|
}
|
File without changes
|
@@ -0,0 +1,58 @@
|
|
1
|
+
{
|
2
|
+
"schema_type": "package",
|
3
|
+
"schema_version": "1.1",
|
4
|
+
"name": "ree_roda",
|
5
|
+
"entry_path": "packages/ree_roda/package/ree_roda.rb",
|
6
|
+
"tags": [
|
7
|
+
"ree_roda"
|
8
|
+
],
|
9
|
+
"depends_on": [
|
10
|
+
{
|
11
|
+
"name": "ree_actions"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
"name": "ree_errors"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"name": "ree_hash"
|
18
|
+
},
|
19
|
+
{
|
20
|
+
"name": "ree_json"
|
21
|
+
},
|
22
|
+
{
|
23
|
+
"name": "ree_logger"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"name": "ree_object"
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"name": "ree_swagger"
|
30
|
+
}
|
31
|
+
],
|
32
|
+
"env_vars": [
|
33
|
+
|
34
|
+
],
|
35
|
+
"objects": [
|
36
|
+
{
|
37
|
+
"name": "build_action_errors",
|
38
|
+
"schema": "packages/ree_roda/schemas/ree_roda/services/build_action_errors.schema.json",
|
39
|
+
"tags": [
|
40
|
+
"fn"
|
41
|
+
]
|
42
|
+
},
|
43
|
+
{
|
44
|
+
"name": "build_swagger_from_actions",
|
45
|
+
"schema": "packages/ree_roda/schemas/ree_roda/services/build_swagger_from_actions.schema.json",
|
46
|
+
"tags": [
|
47
|
+
"fn"
|
48
|
+
]
|
49
|
+
},
|
50
|
+
{
|
51
|
+
"name": "status_from_error",
|
52
|
+
"schema": "packages/ree_roda/schemas/ree_roda/services/status_from_error.schema.json",
|
53
|
+
"tags": [
|
54
|
+
"fn"
|
55
|
+
]
|
56
|
+
}
|
57
|
+
]
|
58
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
package_require("ree_errors/error")
|
2
|
+
package_require("ree_mapper/errors/type_error")
|
3
|
+
|
4
|
+
class ReeRoda::App < Roda
|
5
|
+
include Ree::LinkDSL
|
6
|
+
|
7
|
+
link :logger, from: :ree_logger
|
8
|
+
link :status_from_error
|
9
|
+
link :to_json, from: :ree_json
|
10
|
+
|
11
|
+
plugin :error_handler
|
12
|
+
plugin :json_parser
|
13
|
+
plugin :type_routing, default_type: :json
|
14
|
+
|
15
|
+
error do |e|
|
16
|
+
response["Content-Type"] = "application/json"
|
17
|
+
|
18
|
+
if e.is_a?(ReeErrors::Error)
|
19
|
+
body = {
|
20
|
+
code: e.code,
|
21
|
+
message: e.message,
|
22
|
+
type: e.type,
|
23
|
+
}
|
24
|
+
|
25
|
+
response.status = status_from_error(e.type)
|
26
|
+
response.write(to_json(body))
|
27
|
+
response.finish
|
28
|
+
elsif e.is_a?(ReeMapper::TypeError) || e.is_a?(ReeMapper::CoercionError)
|
29
|
+
body = {
|
30
|
+
code: "param",
|
31
|
+
message: e.message,
|
32
|
+
type: :invalid_param,
|
33
|
+
}
|
34
|
+
|
35
|
+
response.status = 400
|
36
|
+
response.write(to_json(body))
|
37
|
+
response.finish
|
38
|
+
else
|
39
|
+
logger.error(e.message, {}, e)
|
40
|
+
response["Content-Type"] = "text/plain"
|
41
|
+
response.status = 500
|
42
|
+
response.write("unhandled server error")
|
43
|
+
response.finish
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|