ree_lib 1.0.86 → 1.0.87

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/.ruby-version +1 -1
  3. data/Gemfile.lock +28 -23
  4. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_array.rb +12 -8
  5. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_jsonb.rb +12 -8
  6. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_array_spec.rb +3 -3
  7. data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_jsonb_spec.rb +4 -4
  8. data/lib/ree_lib/packages/ree_enum/package/ree_enum/base_enum_mapper.rb +5 -5
  9. data/lib/ree_lib/packages/ree_enum/package/ree_enum/integer_value_enum_mapper.rb +5 -5
  10. data/lib/ree_lib/packages/ree_enum/package/ree_enum/string_value_enum_mapper.rb +5 -5
  11. data/lib/ree_lib/packages/ree_enum/spec/ree_enum/dsl_spec.rb +3 -3
  12. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/coercion_error.rb +1 -1
  13. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/error_with_location.rb +25 -0
  14. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/type_error.rb +1 -1
  15. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/field.rb +12 -4
  16. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +12 -6
  17. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory.rb +17 -4
  18. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +8 -8
  19. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/bool.rb +12 -12
  20. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date.rb +13 -13
  21. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date_time.rb +13 -13
  22. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/float.rb +13 -13
  23. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/integer.rb +13 -13
  24. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/rational.rb +13 -13
  25. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/string.rb +12 -12
  26. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/time.rb +13 -13
  27. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/array.rb +73 -21
  28. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper.rb +1 -0
  29. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +10 -6
  30. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_spec.rb +7 -0
  31. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/time_spec.rb +2 -1
  32. data/lib/ree_lib/spec.init.rb +3 -1
  33. data/lib/ree_lib/version.rb +1 -1
  34. metadata +18 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef4605f8eb48973a2e9ee1c9df9fbef06a4e8be6efe39e2ccd06bc2a945649c3
4
- data.tar.gz: 20b1504401c0e996617499d3b9d595bfcfa124036341f0ca81641c7184da5309
3
+ metadata.gz: b5c70eda05d58f496b0eca7cbc95f853dd51c8b9e33b23c1fa1b51a74eb58104
4
+ data.tar.gz: bf15e2be0aa79c7696ec9bfb074c3748c7061a5aec1079c5fa208aa1cbc16f1c
5
5
  SHA512:
6
- metadata.gz: f6969edfb467a49fa80864d8d27701d2379d846ce2cec01ec80dc0da740978a834597687e2da47ddfb21ec8abbc44a9d7779418e53550fd3bb60237279583cd8
7
- data.tar.gz: 463d80dd677fbba864d2c9c9130b88f523e52c0f49c4ee7632ef781ca8c9af5eec19f1230483509bcb981e91b360aa9072918ceaab091ab21bfbb32d207d21e5
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.86)
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
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)
44
+ msgpack (1.7.2)
41
45
  nokogiri (1.16.0-x86_64-darwin)
42
46
  racc (~> 1.4)
43
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.33)
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
@@ -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, got `#{truncate(value.inspect)}`"
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}` should be a Sequel::Postgres::PGArray, got `#{truncate(value.inspect)}`"
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, got `#{truncate(value.inspect)}`"
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}` should be a Sequel::Postgres::JSONB, got `#{truncate(value.inspect)}`"
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, got `1`")
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` should be a Sequel::Postgres::PGArray, got `1`")
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,14 +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, got `\"1\"`")
58
+ }.to raise_error(ReeMapper::TypeError, /`numbers\[0\]` should be an integer, got `\"1\"`/)
59
59
  }
60
60
 
61
61
  it {
62
62
  object = Object.new
63
63
  expect {
64
64
  mapper.db_dump({ any: object })
65
- }.to raise_error(ReeMapper::TypeError, "`any` should be an jsonb primitive, got `#{object.inspect}`")
65
+ }.to raise_error(ReeMapper::TypeError, /`any` should be an jsonb primitive, got `#{object.inspect}`/)
66
66
  }
67
67
  end
68
68
 
@@ -88,14 +88,14 @@ RSpec.describe 'ReeDao::PgJsonb' do
88
88
  it {
89
89
  expect {
90
90
  mapper.db_load({ numbers: Sequel::Postgres::JSONBArray.new([1.1]) })
91
- }.to raise_error(ReeMapper::TypeError, "`numbers[0]` should be an integer, got `1.1`")
91
+ }.to raise_error(ReeMapper::TypeError, /`numbers\[0\]` should be an integer, got `1.1`/)
92
92
  }
93
93
 
94
94
  it {
95
95
  object = Object.new
96
96
  expect {
97
97
  mapper.db_load({ numbers: object })
98
- }.to raise_error(ReeMapper::TypeError, "`numbers` should be a Sequel::Postgres::JSONB, got `#{object.inspect}`")
98
+ }.to raise_error(ReeMapper::TypeError, /`numbers` should be a Sequel::Postgres::JSONB, got `#{object.inspect}`/)
99
99
  }
100
100
  end
101
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}, got `#{truncate(value.inspect)}`"
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
@@ -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}, got `#{truncate(value.inspect)}`"
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}, got `#{truncate(value.inspect)}`"
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,7 @@ 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"], got `"invalid"`')
155
+ }.to raise_error(ReeMapper::CoercionError, /`type` should be one of \["account"\], got `"invalid"`/)
156
156
 
157
157
  expect {
158
158
  mapper.db_load({
@@ -160,7 +160,7 @@ RSpec.describe ReeEnum::DSL do
160
160
  type: 'invalid',
161
161
  number: 0,
162
162
  })
163
- }.to raise_error(ReeMapper::CoercionError, '`type` should be one of ["account"], got `"invalid"`')
163
+ }.to raise_error(ReeMapper::CoercionError, /`type` should be one of \["account"\], got `"invalid"`/)
164
164
 
165
165
  expect(
166
166
  mapper.cast({
@@ -242,4 +242,4 @@ RSpec.describe ReeEnum::DSL do
242
242
  swagger_definition_fetcher.call(TestReeEnum::ContentTypes.type_for_mapper, -> {})
243
243
  )
244
244
  }
245
- 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)
@@ -43,7 +43,13 @@ class ReeMapper::MapperFactory
43
43
  raise ReeMapper::UnsupportedTypeError, "type :#{name} should implement `\#{@mapper.strategy_methods.join(', ')}`"
44
44
  end
45
45
 
46
- field = ReeMapper::Field.new(type, field_name, optional: optional, **opts)
46
+ field = ReeMapper::Field.new(
47
+ type,
48
+ field_name,
49
+ optional: optional,
50
+ **opts,
51
+ location: caller_locations&.first&.to_s
52
+ )
47
53
 
48
54
  return field unless field_name
49
55
 
@@ -90,7 +96,8 @@ class ReeMapper::MapperFactory
90
96
 
91
97
  if blk
92
98
  subject = ReeMapper::Field.new(
93
- hash_from_blk(dto: dto, &blk)
99
+ hash_from_blk(dto: dto, &blk),
100
+ location: caller_locations&.first&.to_s,
94
101
  )
95
102
  end
96
103
 
@@ -105,7 +112,13 @@ class ReeMapper::MapperFactory
105
112
  type = ReeMapper::Mapper.build(@mapper.strategies, wrapper.new(subject))
106
113
  type.name = :#{name}
107
114
 
108
- field = ReeMapper::Field.new(type, field_name, optional: optional, **opts)
115
+ field = ReeMapper::Field.new(
116
+ type,
117
+ field_name,
118
+ optional: optional,
119
+ **opts,
120
+ location: caller_locations&.first&.to_s,
121
+ )
109
122
 
110
123
  return field unless field_name
111
124
 
@@ -141,7 +154,7 @@ class ReeMapper::MapperFactory
141
154
 
142
155
  type = hash_from_blk(dto: dto, &blk)
143
156
 
144
- field = ReeMapper::Field.new(type, field_name, **opts)
157
+ field = ReeMapper::Field.new(type, field_name, **opts, location: caller_locations&.first&.to_s)
145
158
 
146
159
  @mapper.add_field(field)
147
160
  end
@@ -1,23 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
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)
4
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Any)
5
+ def serialize(value, name:, location: nil)
6
6
  value
7
7
  end
8
8
 
9
- contract(Any , Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
10
- def cast(value, name:, role: nil)
9
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Any)
10
+ def cast(value, name:, location: nil)
11
11
  value
12
12
  end
13
13
 
14
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
15
- def db_dump(value, name:, role: nil)
14
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Any)
15
+ def db_dump(value, name:, location: nil)
16
16
  value
17
17
  end
18
18
 
19
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Any)
20
- def db_load(value, name:, role: nil)
19
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Any)
20
+ def db_load(value, name:, location: nil)
21
21
  value
22
22
  end
23
23
  end