ree_lib 1.0.85 → 1.0.87

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile.lock +31 -26
  4. data/lib/ree_lib/packages/ree_actions/package/ree_actions/dsl.rb +11 -3
  5. data/lib/ree_lib/packages/ree_actions/package/ree_actions/errors.rb +3 -0
  6. data/lib/ree_lib/packages/ree_actions/package/ree_actions.rb +1 -0
  7. data/lib/ree_lib/packages/ree_actions/spec/ree_actions/dsl_spec.rb +5 -1
  8. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_array.rb +12 -8
  9. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_jsonb.rb +12 -8
  10. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_array_spec.rb +3 -3
  11. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_jsonb_spec.rb +8 -6
  12. data/lib/ree_lib/packages/ree_enum/package/ree_enum/base_enum_mapper.rb +5 -10
  13. data/lib/ree_lib/packages/ree_enum/package/ree_enum/integer_value_enum_mapper.rb +5 -5
  14. data/lib/ree_lib/packages/ree_enum/package/ree_enum/string_value_enum_mapper.rb +5 -5
  15. data/lib/ree_lib/packages/ree_enum/spec/ree_enum/dsl_spec.rb +10 -2
  16. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/coercion_error.rb +1 -1
  17. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/error_with_location.rb +25 -0
  18. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/type_error.rb +1 -1
  19. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/field.rb +12 -4
  20. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +12 -6
  21. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory.rb +17 -4
  22. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/abstract_type.rb +6 -0
  23. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +8 -8
  24. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/bool.rb +12 -12
  25. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date.rb +13 -13
  26. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date_time.rb +13 -13
  27. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/float.rb +13 -13
  28. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/integer.rb +16 -16
  29. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/rational.rb +13 -13
  30. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/string.rb +12 -12
  31. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/time.rb +13 -13
  32. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/abstract_wrapper.rb +7 -0
  33. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/array.rb +73 -21
  34. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper.rb +2 -0
  35. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +10 -6
  36. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_spec.rb +7 -0
  37. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/bool_spec.rb +10 -8
  38. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/date_spec.rb +12 -10
  39. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/date_time_spec.rb +20 -16
  40. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/float_spec.rb +17 -13
  41. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/hash_spec.rb +1 -1
  42. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/integer_spec.rb +14 -14
  43. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/rational_spec.rb +16 -12
  44. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/string_spec.rb +24 -12
  45. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/time_spec.rb +21 -16
  46. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/type_options_spec.rb +4 -4
  47. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/wrappers/array_spec.rb +6 -6
  48. data/lib/ree_lib/packages/ree_roda/package/ree_roda/app.rb +3 -2
  49. data/lib/ree_lib/packages/ree_roda/spec/ree_roda/app_spec.rb +28 -0
  50. data/lib/ree_lib/spec.init.rb +3 -1
  51. data/lib/ree_lib/version.rb +1 -1
  52. metadata +19 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79577e4a77cb22f4a504b2d6944064c878585a683b89c166418aa003c8fd7eb0
4
- data.tar.gz: 8ac9c51bea3e5c2611049a8002d23f191ee621801d5e0582e665f5fca51dbb97
3
+ metadata.gz: b5c70eda05d58f496b0eca7cbc95f853dd51c8b9e33b23c1fa1b51a74eb58104
4
+ data.tar.gz: bf15e2be0aa79c7696ec9bfb074c3748c7061a5aec1079c5fa208aa1cbc16f1c
5
5
  SHA512:
6
- metadata.gz: 889a59aeae260e884cd25948b349866ec840bcdb0b85d02bd44c87cef6cdb5e72511669f86cb8f567f3a9e53fba81a85243af9469563fd0fcfbef6fb387356a9
7
- data.tar.gz: 1880826420b58191ca75292f7dea4a973d3250b93c99e9530a2cafa49d79cb4a1c68be4ee96fb6c6aba19a84fc927a7d22603c4f97f63e9c8141f97aa899e6b9
6
+ metadata.gz: c068ce8ba9567eab38bd06c0bdc01731f223f1f4126ac70f5d49c9fc40a9e5034cb7e3cfb2fd84ef578018a31dd5934b6c9283b9a72b3d58e69bdf265af481ca
7
+ data.tar.gz: e2f1b8a4428e46d27e40f98d9134d47139c5de080eef52eeee63cf5cf9eb86fb76fdc54b6d437c810f8a8d5b71889e180903ee8dce4463e82ec2f2769c3bffdf
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.2.0
1
+ 3.3.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.85)
4
+ ree_lib (1.0.87)
5
+ bigdecimal (~> 3.1.6)
5
6
  binding_of_caller (~> 1.0.0)
6
7
  i18n (~> 1.12.0)
7
8
  loofah (~> 2.18.0)
@@ -14,46 +15,49 @@ PATH
14
15
  GEM
15
16
  remote: https://rubygems.org/
16
17
  specs:
17
- addressable (2.8.1)
18
+ abbrev (0.1.2)
19
+ addressable (2.8.6)
18
20
  public_suffix (>= 2.0.2, < 6.0)
21
+ bigdecimal (3.1.6)
19
22
  binding_of_caller (1.0.0)
20
23
  debug_inspector (>= 0.0.1)
21
- bootsnap (1.16.0)
24
+ bootsnap (1.17.0)
22
25
  msgpack (~> 1.2)
23
- commander (4.6.0)
24
- highline (~> 2.0.0)
26
+ commander (5.0.0)
27
+ highline (~> 3.0.0)
25
28
  concurrent-ruby (1.2.2)
26
29
  crack (0.4.5)
27
30
  rexml
28
31
  crass (1.0.6)
29
- debug_inspector (1.1.0)
32
+ debug_inspector (1.2.0)
30
33
  diff-lcs (1.5.0)
31
- faker (3.2.0)
34
+ faker (3.2.2)
32
35
  i18n (>= 1.8.11, < 2)
33
- hashdiff (1.0.1)
34
- highline (2.0.3)
36
+ hashdiff (1.1.0)
37
+ highline (3.0.0)
38
+ abbrev
35
39
  i18n (1.12.0)
36
40
  concurrent-ruby (~> 1.0)
37
41
  loofah (2.18.0)
38
42
  crass (~> 1.0.2)
39
43
  nokogiri (>= 1.5.9)
40
- msgpack (1.6.0)
41
- nokogiri (1.15.5-x86_64-darwin)
44
+ msgpack (1.7.2)
45
+ nokogiri (1.16.0-x86_64-darwin)
42
46
  racc (~> 1.4)
43
- nokogiri (1.15.5-x86_64-linux)
47
+ nokogiri (1.16.0-x86_64-linux)
44
48
  racc (~> 1.4)
45
49
  oj (3.13.23)
46
50
  pg (1.4.6)
47
- public_suffix (5.0.1)
51
+ public_suffix (5.0.4)
48
52
  racc (1.7.3)
49
- rack (3.0.5)
50
- rack-test (2.0.2)
53
+ rack (3.0.8)
54
+ rack-test (2.1.0)
51
55
  rack (>= 1.3)
52
56
  rainbow (3.1.1)
53
- rake (13.0.6)
54
- ree (1.0.32)
55
- commander (~> 4.6.0)
56
- rexml (3.2.5)
57
+ rake (13.1.0)
58
+ ree (1.0.34)
59
+ commander (~> 5.0.0)
60
+ rexml (3.2.6)
57
61
  roda (3.58.0)
58
62
  rack
59
63
  rollbar (3.3.3)
@@ -61,23 +65,23 @@ GEM
61
65
  rspec-core (~> 3.12.0)
62
66
  rspec-expectations (~> 3.12.0)
63
67
  rspec-mocks (~> 3.12.0)
64
- rspec-core (3.12.1)
68
+ rspec-core (3.12.2)
65
69
  rspec-support (~> 3.12.0)
66
- rspec-expectations (3.12.2)
70
+ rspec-expectations (3.12.3)
67
71
  diff-lcs (>= 1.2.0, < 2.0)
68
72
  rspec-support (~> 3.12.0)
69
- rspec-mocks (3.12.3)
73
+ rspec-mocks (3.12.6)
70
74
  diff-lcs (>= 1.2.0, < 2.0)
71
75
  rspec-support (~> 3.12.0)
72
- rspec-support (3.12.0)
76
+ rspec-support (3.12.1)
73
77
  sequel (5.58.0)
74
78
  sqlite3 (1.4.4)
75
- timecop (0.9.6)
79
+ timecop (0.9.8)
76
80
  tzinfo (2.0.6)
77
81
  concurrent-ruby (~> 1.0)
78
82
  warden (1.2.9)
79
83
  rack (>= 2.0.9)
80
- webmock (3.18.1)
84
+ webmock (3.19.1)
81
85
  addressable (>= 2.8.0)
82
86
  crack (>= 0.3.2)
83
87
  hashdiff (>= 0.4.0, < 2.0.0)
@@ -85,6 +89,7 @@ GEM
85
89
  PLATFORMS
86
90
  x86_64-darwin-19
87
91
  x86_64-darwin-21
92
+ x86_64-darwin-22
88
93
  x86_64-linux
89
94
 
90
95
  DEPENDENCIES
@@ -103,4 +108,4 @@ DEPENDENCIES
103
108
  webmock
104
109
 
105
110
  BUNDLED WITH
106
- 2.3.7
111
+ 2.5.4
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+ package_require("ree_mapper/errors/type_error")
3
+ package_require("ree_mapper/errors/coercion_error")
4
+
1
5
  module ReeActions
2
6
  module DSL
3
7
  def self.included(base)
@@ -57,10 +61,14 @@ module ReeActions
57
61
  raise ArgumentError.new("ActionCaster does not respond to `cast` method")
58
62
  end
59
63
 
60
- __original_call(user_access, caster.cast(attrs))
61
- else
62
- __original_call(user_access, attrs)
64
+ attrs = begin
65
+ caster.cast(attrs)
66
+ rescue ReeMapper::TypeError, ReeMapper::CoercionError => e
67
+ raise ReeActions::ParamError, e.message
68
+ end
63
69
  end
70
+
71
+ __original_call(user_access, attrs)
64
72
  ensure
65
73
  __ree_dao_drop_cache
66
74
  end
@@ -0,0 +1,3 @@
1
+ module ReeActions
2
+ ParamError = Class.new(StandardError)
3
+ end
@@ -9,4 +9,5 @@ module ReeActions
9
9
  end
10
10
  end
11
11
 
12
+ require_relative "ree_actions/errors"
12
13
  require_relative "ree_actions/dsl"
@@ -59,6 +59,10 @@ RSpec.describe ReeActions::DSL, type: [:autoclean] do
59
59
 
60
60
  result = ReeActionsTest::TestAction.new.call('user_access', {user_id: 1})
61
61
  expect(result).to eq(1)
62
+
63
+ expect {
64
+ ReeActionsTest::TestAction.new.call('user_access', {user_id: 'not integer'})
65
+ }.to raise_error(ReeActions::ParamError)
62
66
  }
63
67
 
64
68
  it {
@@ -161,7 +165,7 @@ RSpec.describe ReeActions::DSL, type: [:autoclean] do
161
165
  users_dao.put(ReeActionsTest::User.new(name: 'Sam', age: 19))
162
166
  end.join
163
167
  end.join
164
-
168
+
165
169
  $thread_cache = ReeDao::DaoCache.new.get(:users, $user.id)
166
170
 
167
171
  attrs[:user_id]
@@ -8,12 +8,13 @@ class ReeDao::PgArray < ReeMapper::AbstractWrapper
8
8
  Kwargs[
9
9
  name: String,
10
10
  role: Nilor[Symbol, ArrayOf[Symbol]],
11
- fields_filters: ArrayOf[ReeMapper::FieldsFilter]
11
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
12
+ location: Nilor[String],
12
13
  ] => Or[Sequel::Postgres::PGArray, String]
13
14
  )
14
- def db_dump(value, name:, role: nil, fields_filters: [])
15
+ def db_dump(value, name:, role: nil, fields_filters: [], location: nil)
15
16
  if !value.is_a?(Array)
16
- raise ReeMapper::TypeError, "`#{name}` should be an array"
17
+ raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
17
18
  end
18
19
 
19
20
  value = value.map.with_index do |el, index|
@@ -21,7 +22,8 @@ class ReeDao::PgArray < ReeMapper::AbstractWrapper
21
22
  el,
22
23
  name: "#{name}[#{index}]",
23
24
  role: role,
24
- fields_filters: fields_filters + [subject.fields_filter]
25
+ fields_filters: fields_filters + [subject.fields_filter],
26
+ location: subject.location,
25
27
  )
26
28
  end
27
29
 
@@ -37,12 +39,13 @@ class ReeDao::PgArray < ReeMapper::AbstractWrapper
37
39
  Kwargs[
38
40
  name: String,
39
41
  role: Nilor[Symbol, ArrayOf[Symbol]],
40
- fields_filters: ArrayOf[ReeMapper::FieldsFilter]
42
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
43
+ location: Nilor[String],
41
44
  ] => Array
42
45
  ).throws(ReeMapper::TypeError)
43
- def db_load(value, name:, role: nil, fields_filters: [])
46
+ def db_load(value, name:, role: nil, fields_filters: [], location: nil)
44
47
  if !value.is_a?(Sequel::Postgres::PGArray)
45
- raise ReeMapper::TypeError, "`#{name}` is not Sequel::Postgres::PGArray"
48
+ raise ReeMapper::TypeError.new("`#{name}` should be a Sequel::Postgres::PGArray, got `#{truncate(value.inspect)}`", location)
46
49
  end
47
50
 
48
51
  value.map.with_index do |val, index|
@@ -50,7 +53,8 @@ class ReeDao::PgArray < ReeMapper::AbstractWrapper
50
53
  val,
51
54
  name: "#{name}[#{index}]",
52
55
  role: role,
53
- fields_filters: fields_filters + [subject.fields_filter]
56
+ fields_filters: fields_filters + [subject.fields_filter],
57
+ location: subject.location,
54
58
  )
55
59
  end
56
60
  end
@@ -8,7 +8,8 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
8
8
  Kwargs[
9
9
  name: String,
10
10
  role: Nilor[Symbol, ArrayOf[Symbol]],
11
- fields_filters: ArrayOf[ReeMapper::FieldsFilter]
11
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
12
+ location: Nilor[String],
12
13
  ] => Or[
13
14
  Sequel::Postgres::JSONBHash,
14
15
  Sequel::Postgres::JSONBArray,
@@ -20,18 +21,19 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
20
21
  Sequel::Postgres::JSONBNull
21
22
  ]
22
23
  ).throws(ReeMapper::TypeError)
23
- def db_dump(value, name:, role: nil, fields_filters: [])
24
+ def db_dump(value, name:, role: nil, fields_filters: [], location: nil)
24
25
  value = subject.type.db_dump(
25
26
  value,
26
27
  name: name,
27
28
  role: role,
28
- fields_filters: fields_filters + [subject.fields_filter]
29
+ fields_filters: fields_filters + [subject.fields_filter],
30
+ location: subject.location,
29
31
  )
30
32
 
31
33
  begin
32
34
  Sequel.pg_jsonb_wrap(value)
33
35
  rescue Sequel::Error
34
- raise ReeMapper::TypeError, "`#{name}` should be an jsonb primitive"
36
+ raise ReeMapper::TypeError.new("`#{name}` should be an jsonb primitive, got `#{truncate(value.inspect)}`", location)
35
37
  end
36
38
  end
37
39
 
@@ -40,7 +42,8 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
40
42
  Kwargs[
41
43
  name: String,
42
44
  role: Nilor[Symbol, ArrayOf[Symbol]],
43
- fields_filters: ArrayOf[ReeMapper::FieldsFilter]
45
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
46
+ location: Nilor[String],
44
47
  ] => Or[
45
48
  Hash,
46
49
  Array,
@@ -52,7 +55,7 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
52
55
  Rational,
53
56
  ]
54
57
  ).throws(ReeMapper::TypeError)
55
- def db_load(value, name:, role: nil, fields_filters: [])
58
+ def db_load(value, name:, role: nil, fields_filters: [], location: nil)
56
59
  value = case value
57
60
  when Sequel::Postgres::JSONBHash
58
61
  ReeObject::ToHash.new.call(value.to_h)
@@ -61,14 +64,15 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
61
64
  when Numeric, String, TrueClass, FalseClass, NilClass
62
65
  value
63
66
  else
64
- raise ReeMapper::TypeError, "`#{name}` is not Sequel::Postgres::JSONB"
67
+ raise ReeMapper::TypeError.new("`#{name}` should be a Sequel::Postgres::JSONB, got `#{truncate(value.inspect)}`", location)
65
68
  end
66
69
 
67
70
  subject.type.db_load(
68
71
  value,
69
72
  name: name,
70
73
  role: role,
71
- fields_filters: fields_filters + [subject.fields_filter]
74
+ fields_filters: fields_filters + [subject.fields_filter],
75
+ location: subject.location,
72
76
  )
73
77
  end
74
78
  end
@@ -46,7 +46,7 @@ RSpec.describe 'ReeDao::PgArray' do
46
46
  it {
47
47
  expect {
48
48
  mapper.db_dump({ tags: 1 })
49
- }.to raise_error(ReeMapper::TypeError, "`tags` should be an array")
49
+ }.to raise_error(ReeMapper::TypeError, /`tags` should be an array, got `1`/)
50
50
  }
51
51
  end
52
52
 
@@ -66,7 +66,7 @@ RSpec.describe 'ReeDao::PgArray' do
66
66
  mapper.db_load({
67
67
  tags: 1
68
68
  })
69
- }.to raise_error(ReeMapper::TypeError, "`tags` is not Sequel::Postgres::PGArray")
69
+ }.to raise_error(ReeMapper::TypeError, /`tags` should be a Sequel::Postgres::PGArray, got `1`/)
70
70
  }
71
71
  end
72
- end
72
+ end
@@ -55,13 +55,14 @@ RSpec.describe 'ReeDao::PgJsonb' do
55
55
  it {
56
56
  expect {
57
57
  mapper.db_dump({ numbers: ['1'] })
58
- }.to raise_error(ReeMapper::TypeError, "`numbers[0]` should be an integer")
58
+ }.to raise_error(ReeMapper::TypeError, /`numbers\[0\]` should be an integer, got `\"1\"`/)
59
59
  }
60
60
 
61
61
  it {
62
+ object = Object.new
62
63
  expect {
63
- mapper.db_dump({ any: Object.new })
64
- }.to raise_error(ReeMapper::TypeError, "`any` should be an jsonb primitive")
64
+ mapper.db_dump({ any: object })
65
+ }.to raise_error(ReeMapper::TypeError, /`any` should be an jsonb primitive, got `#{object.inspect}`/)
65
66
  }
66
67
  end
67
68
 
@@ -87,13 +88,14 @@ RSpec.describe 'ReeDao::PgJsonb' do
87
88
  it {
88
89
  expect {
89
90
  mapper.db_load({ numbers: Sequel::Postgres::JSONBArray.new([1.1]) })
90
- }.to raise_error(ReeMapper::TypeError, "`numbers[0]` should be an integer")
91
+ }.to raise_error(ReeMapper::TypeError, /`numbers\[0\]` should be an integer, got `1.1`/)
91
92
  }
92
93
 
93
94
  it {
95
+ object = Object.new
94
96
  expect {
95
- mapper.db_load({ numbers: Object.new })
96
- }.to raise_error(ReeMapper::TypeError, "`numbers` is not Sequel::Postgres::JSONB")
97
+ mapper.db_load({ numbers: object })
98
+ }.to raise_error(ReeMapper::TypeError, /`numbers` should be a Sequel::Postgres::JSONB, got `#{object.inspect}`/)
97
99
  }
98
100
  end
99
101
  end
@@ -12,10 +12,10 @@ class ReeEnum::BaseEnumMapper < ReeMapper::AbstractType
12
12
  ReeEnum::Value,
13
13
  Kwargs[
14
14
  name: String,
15
- role: Nilor[Symbol, ArrayOf[Symbol]]
15
+ location: Nilor[String],
16
16
  ] => Or[Integer, String]
17
17
  )
18
- def db_dump(value, name:, role: nil)
18
+ def db_dump(value, name:, location: nil)
19
19
  value.mapped_value
20
20
  end
21
21
 
@@ -23,14 +23,14 @@ class ReeEnum::BaseEnumMapper < ReeMapper::AbstractType
23
23
  Or[Integer, String],
24
24
  Kwargs[
25
25
  name: String,
26
- role: Nilor[Symbol, ArrayOf[Symbol]]
26
+ location: Nilor[String],
27
27
  ] => ReeEnum::Value
28
28
  ).throws(ReeMapper::CoercionError)
29
- def db_load(value, name:, role: nil)
29
+ def db_load(value, name:, location: nil)
30
30
  enum_val = @enum.get_values.by_mapped_value(value)
31
31
 
32
32
  if !enum_val
33
- raise ReeMapper::CoercionError, "`#{name}` should be one of #{enum_inspection}"
33
+ raise ReeMapper::CoercionError.new("`#{name}` should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`", location)
34
34
  end
35
35
 
36
36
  enum_val
@@ -41,9 +41,4 @@ class ReeEnum::BaseEnumMapper < ReeMapper::AbstractType
41
41
  def enum_inspection
42
42
  @enum_inspection ||= truncate(@enum.get_values.each.map(&:to_s).inspect)
43
43
  end
44
-
45
- def truncate(str, limit = 180)
46
- return str if str.length <= limit
47
- "#{str[0..limit]}..."
48
- end
49
44
  end
@@ -6,10 +6,10 @@ class ReeEnum::IntegerValueEnumMapper < ReeEnum::BaseEnumMapper
6
6
  ReeEnum::Value,
7
7
  Kwargs[
8
8
  name: String,
9
- role: Nilor[Symbol, ArrayOf[Symbol]]
9
+ location: Nilor[String],
10
10
  ] => Integer
11
11
  )
12
- def serialize(value, name:, role: nil)
12
+ def serialize(value, name:, location: nil)
13
13
  value.value
14
14
  end
15
15
 
@@ -17,10 +17,10 @@ class ReeEnum::IntegerValueEnumMapper < ReeEnum::BaseEnumMapper
17
17
  Any,
18
18
  Kwargs[
19
19
  name: String,
20
- role: Nilor[Symbol, ArrayOf[Symbol]]
20
+ location: Nilor[String],
21
21
  ] => ReeEnum::Value
22
22
  ).throws(ReeMapper::CoercionError)
23
- def cast(value, name:, role: nil)
23
+ def cast(value, name:, location: nil)
24
24
  enum_value = case value
25
25
  when Integer
26
26
  @enum.get_values.by_value(value)
@@ -34,7 +34,7 @@ class ReeEnum::IntegerValueEnumMapper < ReeEnum::BaseEnumMapper
34
34
  end
35
35
 
36
36
  if enum_value.nil?
37
- raise ReeMapper::CoercionError, "`#{name}` should be one of #{enum_inspection}"
37
+ raise ReeMapper::CoercionError.new("`#{name}` should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`", location)
38
38
  end
39
39
 
40
40
  enum_value
@@ -6,10 +6,10 @@ class ReeEnum::StringValueEnumMapper < ReeEnum::BaseEnumMapper
6
6
  ReeEnum::Value,
7
7
  Kwargs[
8
8
  name: String,
9
- role: Nilor[Symbol, ArrayOf[Symbol]]
9
+ location: Nilor[String],
10
10
  ] => String
11
11
  )
12
- def serialize(value, name:, role: nil)
12
+ def serialize(value, name:, location: nil)
13
13
  value.value
14
14
  end
15
15
 
@@ -17,10 +17,10 @@ class ReeEnum::StringValueEnumMapper < ReeEnum::BaseEnumMapper
17
17
  Any,
18
18
  Kwargs[
19
19
  name: String,
20
- role: Nilor[Symbol, ArrayOf[Symbol]]
20
+ location: Nilor[String],
21
21
  ] => ReeEnum::Value
22
22
  ).throws(ReeMapper::CoercionError)
23
- def cast(value, name:, role: nil)
23
+ def cast(value, name:, location: nil)
24
24
  enum_value = case value
25
25
  when String
26
26
  @enum.get_values.by_value(value)
@@ -29,7 +29,7 @@ class ReeEnum::StringValueEnumMapper < ReeEnum::BaseEnumMapper
29
29
  end
30
30
 
31
31
  if enum_value.nil?
32
- raise ReeMapper::CoercionError, "`#{name}` should be one of #{enum_inspection}"
32
+ raise ReeMapper::CoercionError.new("`#{name}` should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`", location)
33
33
  end
34
34
 
35
35
  enum_value
@@ -152,7 +152,15 @@ RSpec.describe ReeEnum::DSL do
152
152
  type: 'invalid',
153
153
  number: 0,
154
154
  })
155
- }.to raise_error(ReeMapper::CoercionError, '`type` should be one of ["account"]')
155
+ }.to raise_error(ReeMapper::CoercionError, /`type` should be one of \["account"\], got `"invalid"`/)
156
+
157
+ expect {
158
+ mapper.db_load({
159
+ state: 'first',
160
+ type: 'invalid',
161
+ number: 0,
162
+ })
163
+ }.to raise_error(ReeMapper::CoercionError, /`type` should be one of \["account"\], got `"invalid"`/)
156
164
 
157
165
  expect(
158
166
  mapper.cast({
@@ -234,4 +242,4 @@ RSpec.describe ReeEnum::DSL do
234
242
  swagger_definition_fetcher.call(TestReeEnum::ContentTypes.type_for_mapper, -> {})
235
243
  )
236
244
  }
237
- end
245
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class ReeMapper::CoercionError < ReeMapper::Error
3
+ class ReeMapper::CoercionError < ReeMapper::ErrorWithLocation
4
4
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ReeMapper::ErrorWithLocation < ReeMapper::Error
4
+ attr_reader :location
5
+
6
+ def initialize(message, location = nil)
7
+ if message.is_a?(String) && location && ENV["RUBY_ENV"] == "test"
8
+ message = "#{message}, located at #{location}"
9
+ end
10
+
11
+ super(message)
12
+ @location = location
13
+ end
14
+
15
+ def full_message(...)
16
+ msg = super
17
+ return msg if location.nil?
18
+
19
+ idx = msg.index(/\).*\n/)
20
+ return msg if idx.nil?
21
+ return msg if ENV["RUBY_ENV"] == "test"
22
+
23
+ msg.insert(idx + 1, ", located at #{location}")
24
+ end
25
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class ReeMapper::TypeError < ReeMapper::Error
3
+ class ReeMapper::TypeError < ReeMapper::ErrorWithLocation
4
4
  end
@@ -3,7 +3,7 @@
3
3
  class ReeMapper::Field
4
4
  attr_reader :type, :name, :from, :doc, :optional, :null, :roles, :default,
5
5
  :name_as_str, :name_as_instance_var_name, :from_as_str,
6
- :fields_filter
6
+ :fields_filter, :location
7
7
 
8
8
  NO_DEFAULT = Object.new.freeze
9
9
 
@@ -18,11 +18,12 @@ class ReeMapper::Field
18
18
  role: Nilor[ArrayOf[Symbol], Symbol],
19
19
  default: Any,
20
20
  only: Nilor[ReeMapper::FilterFieldsContract],
21
- except: Nilor[ReeMapper::FilterFieldsContract]
21
+ except: Nilor[ReeMapper::FilterFieldsContract],
22
+ location: Nilor[String],
22
23
  ] => Any
23
24
  ).throws(ArgumentError)
24
- def initialize(type, name = nil, from: nil, doc: nil, optional: false, null: false, role: nil, default: NO_DEFAULT,
25
- only: nil, except: nil)
25
+ def initialize(type, name = nil, from: nil, doc: nil, optional: false, null: false, role: nil, default: NO_DEFAULT,
26
+ only: nil, except: nil, location: nil)
26
27
  @type = type
27
28
  @name = name
28
29
  @from = from || name
@@ -38,6 +39,13 @@ class ReeMapper::Field
38
39
  @name_as_instance_var_name = :"@#{@name}"
39
40
  @from_as_str = @from.to_s
40
41
 
42
+ @location = location
43
+ if @location
44
+ @location = @location
45
+ .sub(Ree.root_dir, ".")
46
+ .sub(/:in.+/, "")
47
+ end
48
+
41
49
  raise ArgumentError, 'required fields do not support defaults' if has_default? && !optional
42
50
  end
43
51
 
@@ -23,19 +23,19 @@ class ReeMapper::Mapper
23
23
 
24
24
  if type
25
25
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
26
- def #{method}(obj, name: nil, role: nil, only: nil, except: nil, fields_filters: [])
26
+ def #{method}(obj, name: nil, role: nil, only: nil, except: nil, fields_filters: [], location: nil)
27
27
  #{
28
28
  if type.is_a?(ReeMapper::AbstractWrapper)
29
- "@type.#{method}(obj, name: name, role: role, fields_filters: fields_filters)"
29
+ "@type.#{method}(obj, name: name, role: role, fields_filters: fields_filters, location: location)"
30
30
  else
31
- "@type.#{method}(obj, name: name, role: role)"
31
+ "@type.#{method}(obj, name: name, location: location)"
32
32
  end
33
33
  }
34
34
  end
35
35
  RUBY
36
36
  else
37
37
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
38
- def #{method}(obj, name: nil, role: nil, only: nil, except: nil, fields_filters: [])
38
+ def #{method}(obj, name: nil, role: nil, only: nil, except: nil, fields_filters: [], location: nil)
39
39
  if only && !ReeMapper::FilterFieldsContract.valid?(only)
40
40
  raise ReeMapper::ArgumentError, "Invalid `only` format"
41
41
  end
@@ -56,7 +56,7 @@ class ReeMapper::Mapper
56
56
  is_optional = field.optional || @#{method}_strategy.always_optional
57
57
 
58
58
  if !is_with_value && !is_optional
59
- raise ReeMapper::TypeError, "Missing required field `\#{field.from_as_str}` for `\#{name || 'root'}`"
59
+ raise ReeMapper::TypeError.new("Missing required field `\#{field.from_as_str}` for `\#{name || 'root'}`", field.location)
60
60
  end
61
61
 
62
62
  next if !is_with_value && !field.has_default?
@@ -73,7 +73,13 @@ class ReeMapper::Mapper
73
73
  nested_fields_filters = field_fields_filters.map { _1.filter_for(field.name) }
74
74
  nested_fields_filters += [field.fields_filter]
75
75
 
76
- value = field.type.#{method}(value, name: nested_name, role: role, fields_filters: nested_fields_filters)
76
+ value = field.type.#{method}(
77
+ value,
78
+ name: nested_name,
79
+ role: role,
80
+ fields_filters: nested_fields_filters,
81
+ location: field.location,
82
+ )
77
83
  end
78
84
 
79
85
  @#{method}_strategy.assign_value(acc, field, value)