ree_lib 1.0.93 → 1.0.95

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.
Files changed (71) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +41 -36
  4. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_array.rb +34 -26
  5. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_jsonb.rb +35 -25
  6. data/lib/ree_lib/packages/ree_enum/package/ree_enum/base_enum_mapper.rb +6 -18
  7. data/lib/ree_lib/packages/ree_enum/package/ree_enum/integer_value_enum_mapper.rb +6 -18
  8. data/lib/ree_lib/packages/ree_enum/package/ree_enum/string_value_enum_mapper.rb +6 -18
  9. data/lib/ree_lib/packages/ree_errors/Package.schema.json +10 -7
  10. data/lib/ree_lib/packages/ree_errors/package/ree_errors/auth_error.rb +8 -8
  11. data/lib/ree_lib/packages/ree_errors/package/ree_errors/build_error.rb +4 -2
  12. data/lib/ree_lib/packages/ree_errors/package/ree_errors/conflict_error.rb +8 -8
  13. data/lib/ree_lib/packages/ree_errors/package/ree_errors/error.rb +89 -6
  14. data/lib/ree_lib/packages/ree_errors/package/ree_errors/invalid_param_error.rb +9 -9
  15. data/lib/ree_lib/packages/ree_errors/package/ree_errors/not_found_error.rb +8 -8
  16. data/lib/ree_lib/packages/ree_errors/package/ree_errors/payment_required_error.rb +8 -8
  17. data/lib/ree_lib/packages/ree_errors/package/ree_errors/permission_error.rb +8 -8
  18. data/lib/ree_lib/packages/ree_errors/package/ree_errors/validation_error.rb +8 -8
  19. data/lib/ree_lib/packages/ree_errors/package/ree_errors.rb +1 -0
  20. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/auth_error.schema.json +24 -1
  21. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/build_error.schema.json +10 -0
  22. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/conflict_error.schema.json +24 -1
  23. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/invalid_param_error.schema.json +24 -1
  24. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/not_found_error.schema.json +24 -1
  25. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/payment_required_error.schema.json +24 -1
  26. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/permission_error.schema.json +24 -1
  27. data/lib/ree_lib/packages/ree_errors/schemas/ree_errors/validation_error.schema.json +24 -1
  28. data/lib/ree_lib/packages/ree_errors/spec/ree_errors/auth_error_spec.rb +22 -8
  29. data/lib/ree_lib/packages/ree_errors/spec/ree_errors/invalid_param_error_spec.rb +3 -1
  30. data/lib/ree_lib/packages/ree_errors/spec/ree_errors/locales/en.yml +6 -1
  31. data/lib/ree_lib/packages/ree_errors/spec/ree_errors/not_found_error_spec.rb +3 -1
  32. data/lib/ree_lib/packages/ree_errors/spec/ree_errors/payment_required_error_spec.rb +3 -1
  33. data/lib/ree_lib/packages/ree_errors/spec/ree_errors/permission_error_spec.rb +3 -1
  34. data/lib/ree_lib/packages/ree_errors/spec/ree_errors/validation_error_spec.rb +3 -1
  35. data/lib/ree_lib/packages/ree_i18n/Package.schema.json +7 -0
  36. data/lib/ree_lib/packages/ree_i18n/package/ree_i18n/functions/check_locale_exists.rb +12 -0
  37. data/lib/ree_lib/packages/ree_i18n/schemas/ree_i18n/functions/check_locale_exists.schema.json +33 -0
  38. data/lib/ree_lib/packages/ree_i18n/spec/ree_i18n/functions/check_locale_exists.rb +16 -0
  39. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/error_with_location.rb +47 -14
  40. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/field.rb +1 -1
  41. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/fields_filter.rb +11 -20
  42. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +36 -48
  43. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/abstract_type.rb +2 -2
  44. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +8 -8
  45. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/bool.rb +12 -12
  46. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date.rb +14 -14
  47. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date_time.rb +13 -13
  48. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/float.rb +14 -14
  49. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/integer.rb +13 -13
  50. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/rational.rb +14 -14
  51. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/string.rb +12 -12
  52. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/time.rb +13 -13
  53. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/array.rb +88 -80
  54. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/benchmarks/mapper_benchmark_spec.rb +41 -1
  55. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +17 -6
  56. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/hash_spec.rb +1 -1
  57. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/type_options_spec.rb +7 -26
  58. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/services/build_swagger_from_routes_spec.rb +7 -4
  59. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/services/locales/en.yml +3 -1
  60. data/lib/ree_lib/packages/ree_string/package/ree_string/functions/deconstantize.rb +1 -1
  61. data/lib/ree_lib/packages/ree_swagger/Package.schema.json +3 -0
  62. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_parameters.rb +2 -1
  63. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_request_body_schema.rb +12 -5
  64. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_serializer_schema.rb +12 -5
  65. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger.rb +1 -0
  66. data/lib/ree_lib/packages/ree_swagger/schemas/ree_swagger/functions/build_parameters.schema.json +8 -0
  67. data/lib/ree_lib/packages/ree_swagger/schemas/ree_swagger/functions/build_request_body_schema.schema.json +1 -1
  68. data/lib/ree_lib/packages/ree_swagger/schemas/ree_swagger/functions/build_serializer_schema.schema.json +1 -1
  69. data/lib/ree_lib/version.rb +1 -1
  70. metadata +5 -3
  71. data/lib/ree_lib/packages/ree_errors/package/ree_errors/error_factory.rb +0 -15
@@ -1,39 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::Rational < ReeMapper::AbstractType
4
- contract(Any, Kwargs[name: String, location: Nilor[String]] => Rational).throws(ReeMapper::TypeError)
5
- def serialize(value, name:, location: nil)
4
+ contract(Any => Rational).throws(ReeMapper::TypeError)
5
+ def serialize(value)
6
6
  if value.is_a?(Rational)
7
7
  value
8
8
  else
9
- raise ReeMapper::TypeError.new("`#{name}` should be a rational, got `#{truncate(value.inspect)}`", location)
9
+ raise ReeMapper::TypeError.new("should be a rational, got `#{truncate(value.inspect)}`")
10
10
  end
11
11
  end
12
12
 
13
- contract(Any, Kwargs[name: String, location: Nilor[String]] => Rational).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
- def cast(value, name:, location: nil)
13
+ contract(Any => Rational).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
+ def cast(value)
15
15
  if value.is_a?(Rational)
16
16
  value
17
17
  elsif value.is_a?(String)
18
18
  begin
19
19
  Rational(value)
20
- rescue ArgumentError, ZeroDivisionError => e
21
- raise ReeMapper::CoercionError.new("`#{name}` is invalid rational, got `#{truncate(value.inspect)}`", location)
20
+ rescue ArgumentError, ZeroDivisionError
21
+ raise ReeMapper::CoercionError.new("is invalid rational, got `#{truncate(value.inspect)}`")
22
22
  end
23
23
  elsif value.is_a?(Numeric)
24
24
  Rational(value)
25
25
  else
26
- raise ReeMapper::TypeError.new("`#{name}` should be a rational, got `#{truncate(value.inspect)}`", location)
26
+ raise ReeMapper::TypeError.new("should be a rational, got `#{truncate(value.inspect)}`")
27
27
  end
28
28
  end
29
29
 
30
- contract(Any, Kwargs[name: String, location: Nilor[String]] => String)
31
- def db_dump(value, name:, location: nil)
32
- serialize(value, name: name, location: location).to_s
30
+ contract(Any => String)
31
+ def db_dump(value)
32
+ serialize(value).to_s
33
33
  end
34
34
 
35
- contract(Any, Kwargs[name: String, location: Nilor[String]] => Rational)
36
- def db_load(value, name:, location: nil)
37
- cast(value, name: name, location: location)
35
+ contract(Any => Rational)
36
+ def db_load(value)
37
+ cast(value)
38
38
  end
39
39
  end
@@ -1,27 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::String < ReeMapper::AbstractType
4
- contract(Any, Kwargs[name: String, location: Nilor[String]] => String).throws(ReeMapper::TypeError)
5
- def serialize(value, name:, location: nil)
4
+ contract(Any => String).throws(ReeMapper::TypeError)
5
+ def serialize(value)
6
6
  if value.is_a? String
7
7
  value
8
8
  else
9
- raise ReeMapper::TypeError.new("`#{name}` should be a string, got `#{truncate(value.inspect)}`", location)
9
+ raise ReeMapper::TypeError.new("should be a string, got `#{truncate(value.inspect)}`")
10
10
  end
11
11
  end
12
12
 
13
- contract(Any, Kwargs[name: String, location: Nilor[String]] => String).throws(ReeMapper::TypeError)
14
- def cast(value, name:, location: nil)
15
- serialize(value, name: name, location: location)
13
+ contract(Any => String).throws(ReeMapper::TypeError)
14
+ def cast(value)
15
+ serialize(value)
16
16
  end
17
17
 
18
- contract(Any, Kwargs[name: String, location: Nilor[String]] => String).throws(ReeMapper::TypeError)
19
- def db_dump(value, name:, location: nil)
20
- serialize(value, name: name, location: location)
18
+ contract(Any => String).throws(ReeMapper::TypeError)
19
+ def db_dump(value)
20
+ serialize(value)
21
21
  end
22
22
 
23
- contract(Any, Kwargs[name: String, location: Nilor[String]] => String).throws(ReeMapper::TypeError)
24
- def db_load(value, name:, location: nil)
25
- serialize(value, name: name, location: location)
23
+ contract(Any => String).throws(ReeMapper::TypeError)
24
+ def db_load(value)
25
+ serialize(value)
26
26
  end
27
27
  end
@@ -3,17 +3,17 @@
3
3
  require 'time'
4
4
 
5
5
  class ReeMapper::Time < ReeMapper::AbstractType
6
- contract(Any, Kwargs[name: String, location: Nilor[String]] => Time).throws(ReeMapper::TypeError)
7
- def serialize(value, name:, location: nil)
6
+ contract(Any => Time).throws(ReeMapper::TypeError)
7
+ def serialize(value)
8
8
  if value.class == Time
9
9
  value
10
10
  else
11
- raise ReeMapper::TypeError.new("`#{name}` should be a time, got `#{truncate(value.inspect)}`", location)
11
+ raise ReeMapper::TypeError.new("should be a time, got `#{truncate(value.inspect)}`")
12
12
  end
13
13
  end
14
14
 
15
- contract(Any, Kwargs[name: String, location: Nilor[String]] => Time).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
16
- def cast(value, name:, location: nil)
15
+ contract(Any => Time).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
16
+ def cast(value)
17
17
  if value.class == Time
18
18
  value
19
19
  elsif value.class == DateTime
@@ -22,20 +22,20 @@ class ReeMapper::Time < ReeMapper::AbstractType
22
22
  begin
23
23
  Time.parse(value)
24
24
  rescue ArgumentError
25
- raise ReeMapper::CoercionError.new("`#{name}` is invalid time, got `#{truncate(value.inspect)}`", location)
25
+ raise ReeMapper::CoercionError.new("is invalid time, got `#{truncate(value.inspect)}`")
26
26
  end
27
27
  else
28
- raise ReeMapper::TypeError.new("`#{name}` should be a time, got `#{truncate(value.inspect)}`", location)
28
+ raise ReeMapper::TypeError.new("should be a time, got `#{truncate(value.inspect)}`")
29
29
  end
30
30
  end
31
31
 
32
- contract(Any, Kwargs[name: String, location: Nilor[String]] => Time).throws(ReeMapper::TypeError)
33
- def db_dump(value, name:, location: nil)
34
- serialize(value, name: name, location: location)
32
+ contract(Any => Time).throws(ReeMapper::TypeError)
33
+ def db_dump(value)
34
+ serialize(value)
35
35
  end
36
36
 
37
- contract(Any, Kwargs[name: String, location: Nilor[String]] => Time).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
38
- def db_load(value, name:, location: nil)
39
- cast(value, name: name, location: location)
37
+ contract(Any => Time).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
38
+ def db_load(value)
39
+ cast(value)
40
40
  end
41
41
  end
@@ -4,116 +4,124 @@ class ReeMapper::Array < ReeMapper::AbstractWrapper
4
4
  contract(
5
5
  Any,
6
6
  Kwargs[
7
- name: String,
8
7
  role: Nilor[Symbol, ArrayOf[Symbol]],
9
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
10
- location: Nilor[String],
8
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
11
9
  ] => Array
12
10
  ).throws(ReeMapper::TypeError)
13
- def serialize(value, name:, role: nil, fields_filters: [], location: nil)
14
- if value.is_a?(Array)
15
- value.map.with_index {
16
- if _1.nil? && subject.null
17
- _1
18
- else
19
- subject.type.serialize(
20
- _1,
21
- name: "#{name}[#{_2}]",
22
- role: role,
23
- fields_filters: fields_filters + [subject.fields_filter],
24
- location: subject.location,
25
- )
26
- end
27
- }
28
- else
29
- raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
11
+ def serialize(value, role: nil, fields_filters: nil)
12
+ if !value.is_a?(Array)
13
+ raise ReeMapper::TypeError.new("should be an array, got `#{truncate(value.inspect)}`")
14
+ end
15
+
16
+ if subject.fields_filter
17
+ fields_filters = if fields_filters
18
+ fields_filters + [subject.fields_filter]
19
+ else
20
+ [subject.fields_filter]
21
+ end
22
+ end
23
+
24
+ value.map.with_index do |item, idx|
25
+ next nil if item.nil? && subject.null
26
+
27
+ subject.type.serialize(item, role:, fields_filters:)
28
+ rescue ReeMapper::ErrorWithLocation => e
29
+ e.prepend_field_name(idx.to_s)
30
+ e.location ||= subject.location
31
+ raise e
30
32
  end
31
33
  end
32
34
 
33
35
  contract(
34
36
  Any,
35
37
  Kwargs[
36
- name: String,
37
38
  role: Nilor[Symbol, ArrayOf[Symbol]],
38
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
39
- location: Nilor[String],
39
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
40
40
  ] => Array
41
41
  ).throws(ReeMapper::TypeError)
42
- def cast(value, name:, role: nil, fields_filters: [], location: nil)
43
- if value.is_a?(Array)
44
- value.map.with_index {
45
- if _1.nil? && subject.null
46
- _1
47
- else
48
- subject.type.cast(
49
- _1,
50
- name: "#{name}[#{_2}]",
51
- role: role,
52
- fields_filters: fields_filters + [subject.fields_filter],
53
- location: subject.location,
54
- )
55
- end
56
- }
57
- else
58
- raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
42
+ def cast(value, role: nil, fields_filters: nil)
43
+ if !value.is_a?(Array)
44
+ raise ReeMapper::TypeError.new("should be an array, got `#{truncate(value.inspect)}`")
45
+ end
46
+
47
+ if subject.fields_filter
48
+ fields_filters = if fields_filters
49
+ fields_filters + [subject.fields_filter]
50
+ else
51
+ [subject.fields_filter]
52
+ end
53
+ end
54
+
55
+ value.map.with_index do |item, idx|
56
+ next nil if item.nil? && subject.null
57
+
58
+ subject.type.cast(item, role:, fields_filters:)
59
+ rescue ReeMapper::ErrorWithLocation => e
60
+ e.prepend_field_name(idx.to_s)
61
+ e.location ||= subject.location
62
+ raise e
59
63
  end
60
64
  end
61
65
 
62
66
  contract(
63
67
  Any,
64
68
  Kwargs[
65
- name: String,
66
69
  role: Nilor[Symbol, ArrayOf[Symbol]],
67
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
68
- location: Nilor[String],
70
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
69
71
  ] => Array
70
72
  ).throws(ReeMapper::TypeError)
71
- def db_dump(value, name:, role: nil, fields_filters: [], location: nil)
72
- if value.is_a?(Array)
73
- value.map.with_index {
74
- if _1.nil? && subject.null
75
- _1
76
- else
77
- subject.type.db_dump(
78
- _1,
79
- name: "#{name}[#{_2}]",
80
- role: role,
81
- fields_filters: fields_filters + [subject.fields_filter],
82
- location: subject.location,
83
- )
84
- end
85
- }
86
- else
87
- raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
73
+ def db_dump(value, role: nil, fields_filters: nil)
74
+ if !value.is_a?(Array)
75
+ raise ReeMapper::TypeError.new("should be an array, got `#{truncate(value.inspect)}`")
76
+ end
77
+
78
+ if subject.fields_filter
79
+ fields_filters = if fields_filters
80
+ fields_filters + [subject.fields_filter]
81
+ else
82
+ [subject.fields_filter]
83
+ end
84
+ end
85
+
86
+ value.map.with_index do |item, idx|
87
+ next nil if item.nil? && subject.null
88
+
89
+ subject.type.db_dump(item, role:, fields_filters:)
90
+ rescue ReeMapper::ErrorWithLocation => e
91
+ e.prepend_field_name(idx.to_s)
92
+ e.location ||= subject.location
93
+ raise e
88
94
  end
89
95
  end
90
96
 
91
97
  contract(
92
98
  Any,
93
99
  Kwargs[
94
- name: String,
95
100
  role: Nilor[Symbol, ArrayOf[Symbol]],
96
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
97
- location: Nilor[String],
101
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
98
102
  ] => Array
99
103
  ).throws(ReeMapper::TypeError)
100
- def db_load(value, name:, role: nil, fields_filters: [], location: nil)
101
- if value.is_a?(Array)
102
- value.map.with_index {
103
- if _1.nil? && subject.null
104
- _1
105
- else
106
- subject.type.db_load(
107
- _1,
108
- name: "#{name}[#{_2}]",
109
- role: role,
110
- fields_filters: fields_filters + [subject.fields_filter],
111
- location: subject.location,
112
- )
113
- end
114
- }
115
- else
116
- raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
104
+ def db_load(value, role: nil, fields_filters: nil)
105
+ if !value.is_a?(Array)
106
+ raise ReeMapper::TypeError.new("should be an array, got `#{truncate(value.inspect)}`")
107
+ end
108
+
109
+ if subject.fields_filter
110
+ fields_filters = if fields_filters
111
+ fields_filters + [subject.fields_filter]
112
+ else
113
+ [subject.fields_filter]
114
+ end
115
+ end
116
+
117
+ value.map.with_index do |item, idx|
118
+ next nil if item.nil? && subject.null
119
+
120
+ subject.type.db_load(item, role:, fields_filters:)
121
+ rescue ReeMapper::ErrorWithLocation => e
122
+ e.prepend_field_name(idx.to_s)
123
+ e.location ||= subject.location
124
+ raise e
117
125
  end
118
126
  end
119
127
  end
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
  require 'benchmark'
3
3
 
4
+ no_contracts = Ree::Contracts.no_contracts?
5
+ Ree.disable_contracts
6
+
4
7
  package_require "ree_mapper"
5
8
 
6
9
  RSpec.xdescribe 'Mapper Benchmark' do
@@ -25,7 +28,44 @@ RSpec.xdescribe 'Mapper Benchmark' do
25
28
  obj = { my_field: { my_field: { my_field: 1 } } }
26
29
 
27
30
  _benchmark_res = Benchmark.bmbm do |x|
28
- x.report('cast') { 1000.times { mapper.cast(obj) } }
31
+ x.report('cast') { 100000.times { mapper.cast(obj) } }
29
32
  end
30
33
  end
34
+
35
+ xit do
36
+ Ree.disable_contracts
37
+ require "ruby-prof"
38
+ package_require "ree_mapper"
39
+
40
+ mapper = ReeMapper::BuildMapperFactory.new.call(
41
+ strategies: [
42
+ ReeMapper::BuildMapperStrategy.new.call(method: :cast, dto: Hash),
43
+ ]
44
+ ).call.use(:cast) do
45
+ hash :my_field do
46
+ hash :my_field do
47
+ integer :my_field
48
+ end
49
+ end
50
+ end
51
+
52
+ obj = { my_field: { my_field: { my_field: 1 } } }
53
+
54
+ result = RubyProf::Profile.profile do
55
+ mapper.cast(obj)
56
+ end
57
+
58
+ RubyProf::FlatPrinter.new(result).print(STDOUT)
59
+ end
31
60
  end
61
+
62
+ if !no_contracts
63
+ Ree.enable_contracts
64
+ end
65
+
66
+ # version main
67
+ # cast 0.369019 0.001180 0.370199 ( 0.370515)
68
+ # cast 0.356124 0.001060 0.357184 ( 0.357502)
69
+ # version 1.0.93
70
+ # cast 0.791664 0.004125 0.795789 ( 0.796938)
71
+ # cast 0.782544 0.016745 0.799289 ( 0.799759)
@@ -82,12 +82,17 @@ RSpec.describe ReeMapper::MapperFactory do
82
82
  describe '.register_wrapper' do
83
83
  let(:round_wrapper) {
84
84
  Class.new(ReeMapper::AbstractWrapper) do
85
- def serialize(value, name:, location: nil, **opts)
85
+ def serialize(value, **opts)
86
86
  if !value.is_a?(Numeric)
87
- raise ReeMapper::TypeError.new("`#{name}` should be a number, got `#{truncate(value.inspect)}`", location)
87
+ raise ReeMapper::TypeError.new("should be a number, got `#{truncate(value.inspect)}`")
88
88
  end
89
89
 
90
- subject.type.serialize(value.round, name: name, location: subject.location, **opts)
90
+ begin
91
+ subject.type.serialize(value.round, **opts)
92
+ rescue ReeMapper::ErrorWithLocation => e
93
+ e.location ||= subject.location
94
+ raise e
95
+ end
91
96
  end
92
97
  end
93
98
  }
@@ -102,12 +107,18 @@ RSpec.describe ReeMapper::MapperFactory do
102
107
 
103
108
  it 'allow to register caster and serializer with the same name' do
104
109
  caster_round_wrapper = Class.new(ReeMapper::AbstractWrapper) do
105
- def cast(value, name:, location: nil, **opts)
106
- value = subject.type.cast(value, name: name, location: subject.location, **opts)
110
+ def cast(value, **opts)
111
+ value = begin
112
+ subject.type.cast(value, **opts)
113
+ rescue ReeMapper::ErrorWithLocation => e
114
+ e.location ||= subject.location
115
+ raise e
116
+ end
107
117
 
108
118
  if !value.is_a?(Numeric)
109
- raise ReeMapper::TypeError.new("`#{name}` should be a number, got `#{truncate(value.inspect)}`", location)
119
+ raise ReeMapper::TypeError.new("should be a number, got `#{truncate(value.inspect)}`")
110
120
  end
121
+
111
122
  value.round
112
123
  end
113
124
  end
@@ -27,7 +27,7 @@ RSpec.describe 'Mapper Hash' do
27
27
  }
28
28
 
29
29
  it {
30
- expect { mapper.cast({ point: 1 }) }.to raise_error(ReeMapper::TypeError, /Missing required field `x` for `point`/)
30
+ expect { mapper.cast({ point: 1 }) }.to raise_error(ReeMapper::TypeError, /`point\[x\]` is missing required field/)
31
31
  }
32
32
 
33
33
  it {
@@ -116,37 +116,18 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
116
116
  }
117
117
  end
118
118
 
119
- context 'with invalid only' do
119
+ context "with empty nested filter" do
120
120
  let(:mapper) {
121
121
  mapper_factory.call.use(:cast) {
122
- point :point
123
- }
124
- }
125
-
126
- it {
127
- expect {
128
- mapper.cast({}, only: {})
129
- }.to raise_error(
130
- ReeMapper::ArgumentError,
131
- "Invalid `only` format"
132
- )
133
- }
134
- end
135
-
136
- context 'with invalid except' do
137
- let(:mapper) {
138
- mapper_factory.call.use(:cast) {
139
- point :point
122
+ hash :point_wrap do
123
+ point :point
124
+ end
140
125
  }
141
126
  }
142
127
 
143
128
  it {
144
- expect {
145
- mapper.cast({}, except: {})
146
- }.to raise_error(
147
- ReeMapper::ArgumentError,
148
- "Invalid `except` format"
149
- )
129
+ expect(mapper.cast({ point_wrap: { point: { x: 1, y: 1, z: 1 } } }, only: [point_wrap: [:point]]))
130
+ .to eq({ point_wrap: { point: { x: 1, y: 1, z: 1 } } })
150
131
  }
151
132
  end
152
133
  end
@@ -193,7 +174,7 @@ RSpec.describe 'ReeMapper::MapperFactory type options' do
193
174
  }
194
175
 
195
176
  it {
196
- expect { mapper.cast({}) }.to raise_error(ReeMapper::TypeError, /Missing required field `number` for `root`/)
177
+ expect { mapper.cast({}) }.to raise_error(ReeMapper::TypeError, /`number` is missing required field/)
197
178
  }
198
179
 
199
180
  it {
@@ -17,19 +17,22 @@ RSpec.describe :build_swagger_from_routes do
17
17
  package do
18
18
  depends_on :ree_actions
19
19
  depends_on :ree_dao
20
+ depends_on :ree_errors
20
21
  end
21
22
  end
22
23
 
23
24
  class ReeRodaTestSwagger::Cmd
24
25
  include ReeActions::DSL
25
26
 
26
- action :cmd
27
+ action :cmd do
28
+ link :invalid_param_error, from: :ree_errors
29
+ end
27
30
 
28
31
  ActionCaster = build_mapper.use(:cast) do
29
32
  integer :id
30
33
  end
31
34
 
32
- InvalidErr = ReeErrors::ValidationError.build(:invalid, "invalid")
35
+ InvalidErr = invalid_param_error(:invalid, "invalid")
33
36
 
34
37
  contract(Any, Any => Any).throws(InvalidErr)
35
38
  def call(access, attrs)
@@ -71,7 +74,7 @@ RSpec.describe :build_swagger_from_routes do
71
74
  it {
72
75
  swagger = build_swagger_from_routes(routes, "test", "test", "1.0", "https://example.com")
73
76
 
74
- expect(swagger.dig(:paths, "/api/actions", :post, :responses, 422, :description))
75
- .to eq("- type: **validation**, code: **invalid**, message: **invalid**")
77
+ expect(swagger.dig(:paths, "/api/actions", :post, :responses, 400, :description))
78
+ .to eq("- type: **invalid_param**, code: **invalid**, message: **invalid param**")
76
79
  }
77
80
  end
@@ -1,2 +1,4 @@
1
1
  en:
2
- invalid: "invalid"
2
+ ree_roda_test_swagger:
3
+ errors:
4
+ invalid: "invalid param"
@@ -7,7 +7,7 @@ class ReeString::Deconstantize
7
7
 
8
8
  doc(<<~DOC)
9
9
  Removes the rightmost segment from the constant expression in the string.
10
-
10
+
11
11
  deconstantize('Net::HTTP') # => "Net"
12
12
  deconstantize('::Net::HTTP') # => "::Net"
13
13
  deconstantize('String') # => ""
@@ -7,6 +7,9 @@
7
7
  "ree_swagger"
8
8
  ],
9
9
  "depends_on": [
10
+ {
11
+ "name": "ree_array"
12
+ },
10
13
  {
11
14
  "name": "ree_dto"
12
15
  },
@@ -6,6 +6,7 @@ class ReeSwagger::BuildParameters
6
6
  fn :build_parameters do
7
7
  link :get_caster_definition
8
8
  link :build_request_body_schema
9
+ link :wrap, from: :ree_array
9
10
  end
10
11
 
11
12
  ObjectPathParamError = Class.new(StandardError)
@@ -36,7 +37,7 @@ class ReeSwagger::BuildParameters
36
37
  name: field.name_as_str,
37
38
  in: is_path_param ? 'path' : 'query',
38
39
  required: is_path_param || !field.optional,
39
- schema: build_request_body_schema(field.type, [], [field.fields_filter]) || {}
40
+ schema: build_request_body_schema(field.type, [], wrap(field.fields_filter)) || {}
40
41
  }
41
42
 
42
43
  schema[:style] = 'deepObject' if field.type.type.nil?
@@ -10,9 +10,9 @@ class ReeSwagger::BuildRequestBodySchema
10
10
  contract(
11
11
  ReeMapper::Mapper,
12
12
  ArrayOf[Symbol],
13
- ArrayOf[ReeMapper::FieldsFilter] => Nilor[Hash]
13
+ Nilor[ArrayOf[ReeMapper::FieldsFilter]] => Nilor[Hash]
14
14
  )
15
- def call(mapper, path_params = [], fields_filters = [])
15
+ def call(mapper, path_params = [], fields_filters = nil)
16
16
  if mapper.type
17
17
  return get_caster_definition(mapper.type, method(:call).to_proc)
18
18
  end
@@ -20,7 +20,7 @@ class ReeSwagger::BuildRequestBodySchema
20
20
  required_fields = []
21
21
 
22
22
  properties = mapper.fields.each_with_object({}) do |(_name, field), acc|
23
- next unless fields_filters.all? { _1.allow?(field.name) }
23
+ next unless fields_filters.nil? || fields_filters.all? { _1.allow?(field.name) }
24
24
 
25
25
  next if path_params.include?(field.name)
26
26
 
@@ -34,8 +34,15 @@ class ReeSwagger::BuildRequestBodySchema
34
34
  required_fields << field.name.to_s if !field.optional
35
35
  field_mapper = field.type
36
36
 
37
- nested_fields_filters = fields_filters.map { _1.filter_for(field.name) }
38
- nested_fields_filters += [field.fields_filter]
37
+ nested_fields_filters = fields_filters&.filter_map { _1.filter_for(field.name) }
38
+
39
+ if field.fields_filter
40
+ nested_fields_filters = if nested_fields_filters
41
+ nested_fields_filters + [field.fields_filter]
42
+ else
43
+ [field.fields_filter]
44
+ end
45
+ end
39
46
 
40
47
  swagger_type = call(field_mapper, [], nested_fields_filters)
41
48