ree_lib 1.0.86 → 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 (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
@@ -4,33 +4,33 @@ class ReeMapper::Bool < ReeMapper::AbstractType
4
4
  TRUE_CAST_VALUES = ['1', 'true', 'on', 1, true].freeze
5
5
  FALSE_CAST_VALUES = ['0', 'false', 'off', 0, false].freeze
6
6
 
7
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Bool).throws(ReeMapper::TypeError)
8
- def serialize(value, name:, role: nil)
7
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Bool).throws(ReeMapper::TypeError)
8
+ def serialize(value, name:, location: nil)
9
9
  if value.is_a?(TrueClass) || value.is_a?(FalseClass)
10
10
  value
11
11
  else
12
- raise ReeMapper::TypeError, "`#{name}` should be a boolean, got `#{truncate(value.inspect)}`"
12
+ raise ReeMapper::TypeError.new("`#{name}` should be a boolean, got `#{truncate(value.inspect)}`", location)
13
13
  end
14
14
  end
15
15
 
16
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Bool).throws(ReeMapper::CoercionError)
17
- def cast(value, name:, role: nil)
16
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Bool).throws(ReeMapper::CoercionError)
17
+ def cast(value, name:, location: nil)
18
18
  if TRUE_CAST_VALUES.include?(value)
19
19
  true
20
20
  elsif FALSE_CAST_VALUES.include?(value)
21
21
  false
22
22
  else
23
- raise ReeMapper::CoercionError, "`#{name}` is invalid boolean, got `#{truncate(value.inspect)}`"
23
+ raise ReeMapper::CoercionError.new("`#{name}` is invalid boolean, got `#{truncate(value.inspect)}`", location)
24
24
  end
25
25
  end
26
26
 
27
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Bool).throws(ReeMapper::TypeError)
28
- def db_dump(value, name:, role: nil)
29
- serialize(value, name: name, role: role)
27
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Bool).throws(ReeMapper::TypeError)
28
+ def db_dump(value, name:, location: nil)
29
+ serialize(value, name: name, location: location)
30
30
  end
31
31
 
32
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Bool).throws(ReeMapper::CoercionError)
33
- def db_load(value, name:, role: nil)
34
- cast(value, name: name, role: role)
32
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Bool).throws(ReeMapper::CoercionError)
33
+ def db_load(value, name:, location: nil)
34
+ cast(value, name: name, location: location)
35
35
  end
36
36
  end
@@ -3,17 +3,17 @@
3
3
  require 'date'
4
4
 
5
5
  class ReeMapper::Date < ReeMapper::AbstractType
6
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Date).throws(ReeMapper::TypeError)
7
- def serialize(value, name:, role: nil)
6
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Date).throws(ReeMapper::TypeError)
7
+ def serialize(value, name:, location: nil)
8
8
  if value.class == Date
9
9
  value
10
10
  else
11
- raise ReeMapper::TypeError, "`#{name}` should be a date, got `#{truncate(value.inspect)}`"
11
+ raise ReeMapper::TypeError.new("`#{name}` should be a date, got `#{truncate(value.inspect)}`", location)
12
12
  end
13
13
  end
14
14
 
15
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Date).throws(ReeMapper::TypeError, ReeMapper::CoercionError)
16
- def cast(value, name:, role: nil)
15
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Date).throws(ReeMapper::TypeError, ReeMapper::CoercionError)
16
+ def cast(value, name:, location: nil)
17
17
  if value.class == Date
18
18
  value
19
19
  elsif value.class == DateTime || value.class == Time
@@ -22,20 +22,20 @@ class ReeMapper::Date < ReeMapper::AbstractType
22
22
  begin
23
23
  Date.parse(value)
24
24
  rescue ArgumentError => e
25
- raise ReeMapper::CoercionError, "`#{name}` is invalid date, got `#{truncate(value.inspect)}`"
25
+ raise ReeMapper::CoercionError.new("`#{name}` is invalid date, got `#{truncate(value.inspect)}`", location)
26
26
  end
27
27
  else
28
- raise ReeMapper::TypeError, "`#{name}` should be a date, got `#{truncate(value.inspect)}`"
28
+ raise ReeMapper::TypeError.new("`#{name}` should be a date, got `#{truncate(value.inspect)}`", location)
29
29
  end
30
30
  end
31
31
 
32
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Date).throws(ReeMapper::TypeError)
33
- def db_dump(value, name:, role: nil)
34
- serialize(value, name: name, role: role)
32
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Date).throws(ReeMapper::TypeError)
33
+ def db_dump(value, name:, location: nil)
34
+ serialize(value, name: name, location: location)
35
35
  end
36
36
 
37
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Date).throws(ReeMapper::TypeError, ReeMapper::CoercionError)
38
- def db_load(value, name:, role: nil)
39
- cast(value, name: name, role: role)
37
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Date).throws(ReeMapper::TypeError, ReeMapper::CoercionError)
38
+ def db_load(value, name:, location: nil)
39
+ cast(value, name: name, location: location)
40
40
  end
41
41
  end
@@ -3,17 +3,17 @@
3
3
  require 'date'
4
4
 
5
5
  class ReeMapper::DateTime < ReeMapper::AbstractType
6
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => DateTime).throws(ReeMapper::TypeError)
7
- def serialize(value, name:, role: nil)
6
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => DateTime).throws(ReeMapper::TypeError)
7
+ def serialize(value, name:, location: nil)
8
8
  if value.class == DateTime
9
9
  value
10
10
  else
11
- raise ReeMapper::TypeError, "`#{name}` should be a datetime, got `#{truncate(value.inspect)}`"
11
+ raise ReeMapper::TypeError.new("`#{name}` should be a datetime, got `#{truncate(value.inspect)}`", location)
12
12
  end
13
13
  end
14
14
 
15
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => DateTime).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
16
- def cast(value, name:, role: nil)
15
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => DateTime).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
16
+ def cast(value, name:, location: nil)
17
17
  if value.class == DateTime
18
18
  value
19
19
  elsif value.class == Time
@@ -22,20 +22,20 @@ class ReeMapper::DateTime < ReeMapper::AbstractType
22
22
  begin
23
23
  ReeDatetime::InDefaultTimeZone.new.call(DateTime.parse(value))
24
24
  rescue ArgumentError
25
- raise ReeMapper::CoercionError, "`#{name}` is invalid datetime, got `#{truncate(value.inspect)}`"
25
+ raise ReeMapper::CoercionError.new("`#{name}` is invalid datetime, got `#{truncate(value.inspect)}`", location)
26
26
  end
27
27
  else
28
- raise ReeMapper::TypeError, "`#{name}` should be a datetime, got `#{truncate(value.inspect)}`"
28
+ raise ReeMapper::TypeError.new("`#{name}` should be a datetime, got `#{truncate(value.inspect)}`", location)
29
29
  end
30
30
  end
31
31
 
32
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => DateTime).throws(ReeMapper::TypeError)
33
- def db_dump(value, name:, role: nil)
34
- serialize(value, name: name, role: role)
32
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => DateTime).throws(ReeMapper::TypeError)
33
+ def db_dump(value, name:, location: nil)
34
+ serialize(value, name: name, location: location)
35
35
  end
36
36
 
37
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => DateTime).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
38
- def db_load(value, name:, role: nil)
39
- cast(value, name: name, role: role)
37
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => DateTime).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
38
+ def db_load(value, name:, location: nil)
39
+ cast(value, name: name, location: location)
40
40
  end
41
41
  end
@@ -1,39 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::Float < ReeMapper::AbstractType
4
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Float).throws(ReeMapper::TypeError)
5
- def serialize(value, name:, role: nil)
4
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Float).throws(ReeMapper::TypeError)
5
+ def serialize(value, name:, location: nil)
6
6
  if value.is_a?(Float)
7
7
  value
8
8
  else
9
- raise ReeMapper::TypeError, "`#{name}` should be a float, got `#{truncate(value.inspect)}`"
9
+ raise ReeMapper::TypeError.new("`#{name}` should be a float, got `#{truncate(value.inspect)}`", location)
10
10
  end
11
11
  end
12
12
 
13
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Float).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
- def cast(value, name:, role: nil)
13
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Float).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
+ def cast(value, name:, location: nil)
15
15
  if value.is_a?(Numeric)
16
16
  value.to_f
17
17
  elsif value.is_a?(String)
18
18
  begin
19
19
  Float(value)
20
20
  rescue ArgumentError => e
21
- raise ReeMapper::CoercionError, "`#{name}` is invalid float, got `#{truncate(value.inspect)}`"
21
+ raise ReeMapper::CoercionError.new("`#{name}` is invalid float, got `#{truncate(value.inspect)}`", location)
22
22
  end
23
23
  elsif defined?(BigDecimal) && value.is_a?(BigDecimal)
24
24
  value.to_f
25
25
  else
26
- raise ReeMapper::TypeError, "`#{name}` should be a float, got `#{truncate(value.inspect)}`"
26
+ raise ReeMapper::TypeError.new("`#{name}` should be a float, got `#{truncate(value.inspect)}`", location)
27
27
  end
28
28
  end
29
29
 
30
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Float).throws(ReeMapper::CoercionError)
31
- def db_dump(value, name:, role: nil)
32
- serialize(value, name: name, role: role)
30
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Float).throws(ReeMapper::CoercionError)
31
+ def db_dump(value, name:, location: nil)
32
+ serialize(value, name: name, location: location)
33
33
  end
34
34
 
35
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Float).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
36
- def db_load(value, name:, role: nil)
37
- cast(value, name: name, role: role)
35
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Float).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
36
+ def db_load(value, name:, location: nil)
37
+ cast(value, name: name, location: location)
38
38
  end
39
39
  end
@@ -1,37 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::Integer < ReeMapper::AbstractType
4
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Integer).throws(ReeMapper::TypeError)
5
- def serialize(value, name:, role: nil)
4
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Integer).throws(ReeMapper::TypeError)
5
+ def serialize(value, name:, location: nil)
6
6
  if value.is_a? Integer
7
7
  value
8
8
  else
9
- raise ReeMapper::TypeError, "`#{name}` should be an integer, got `#{truncate(value.inspect)}`"
9
+ raise ReeMapper::TypeError.new("`#{name}` should be an integer, got `#{truncate(value.inspect)}`", location)
10
10
  end
11
11
  end
12
12
 
13
- contract(Any , Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]]=> Integer).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
- def cast(value, name:, role: nil)
13
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Integer).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
+ def cast(value, name:, location: nil)
15
15
  if value.is_a?(Integer)
16
16
  value
17
17
  elsif value.is_a?(String)
18
18
  coerced_value = Integer(value, exception: false)
19
19
  if coerced_value.nil?
20
- raise ReeMapper::CoercionError, "`#{name}` is invalid integer, got `#{truncate(value.inspect)}`"
20
+ raise ReeMapper::CoercionError.new("`#{name}` is invalid integer, got `#{truncate(value.inspect)}`", location)
21
21
  end
22
22
  coerced_value
23
23
  else
24
- raise ReeMapper::TypeError, "`#{name}` should be an integer, got `#{truncate(value.inspect)}`"
24
+ raise ReeMapper::TypeError.new("`#{name}` should be an integer, got `#{truncate(value.inspect)}`", location)
25
25
  end
26
26
  end
27
27
 
28
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Integer).throws(ReeMapper::TypeError)
29
- def db_dump(value, name:, role: nil)
30
- serialize(value, name: name, role: role)
28
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Integer).throws(ReeMapper::TypeError)
29
+ def db_dump(value, name:, location: nil)
30
+ serialize(value, name: name, location: location)
31
31
  end
32
32
 
33
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Integer).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
34
- def db_load(value, name:, role: nil)
35
- cast(value, name: name, role: role)
33
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Integer).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
34
+ def db_load(value, name:, location: nil)
35
+ cast(value, name: name, location: location)
36
36
  end
37
37
  end
@@ -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, role: Nilor[Symbol, ArrayOf[Symbol]]] => Rational).throws(ReeMapper::TypeError)
5
- def serialize(value, name:, role: nil)
4
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Rational).throws(ReeMapper::TypeError)
5
+ def serialize(value, name:, location: nil)
6
6
  if value.is_a?(Rational)
7
7
  value
8
8
  else
9
- raise ReeMapper::TypeError, "`#{name}` should be a rational, got `#{truncate(value.inspect)}`"
9
+ raise ReeMapper::TypeError.new("`#{name}` should be a rational, got `#{truncate(value.inspect)}`", location)
10
10
  end
11
11
  end
12
12
 
13
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Rational).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
- def cast(value, name:, role: nil)
13
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Rational).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
+ def cast(value, name:, location: nil)
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
20
  rescue ArgumentError, ZeroDivisionError => e
21
- raise ReeMapper::CoercionError, "`#{name}` is invalid rational, got `#{truncate(value.inspect)}`"
21
+ raise ReeMapper::CoercionError.new("`#{name}` is invalid rational, got `#{truncate(value.inspect)}`", location)
22
22
  end
23
23
  elsif value.is_a?(Numeric)
24
24
  Rational(value)
25
25
  else
26
- raise ReeMapper::TypeError, "`#{name}` should be a rational, got `#{truncate(value.inspect)}`"
26
+ raise ReeMapper::TypeError.new("`#{name}` should be a rational, got `#{truncate(value.inspect)}`", location)
27
27
  end
28
28
  end
29
29
 
30
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => String)
31
- def db_dump(value, name:, role: nil)
32
- serialize(value, name: name, role: role).to_s
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
33
33
  end
34
34
 
35
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Rational)
36
- def db_load(value, name:, role: nil)
37
- cast(value, name: name, role: role)
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)
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, role: Nilor[Symbol, ArrayOf[Symbol]]] => String).throws(ReeMapper::TypeError)
5
- def serialize(value, name:, role: nil)
4
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => String).throws(ReeMapper::TypeError)
5
+ def serialize(value, name:, location: nil)
6
6
  if value.is_a? String
7
7
  value
8
8
  else
9
- raise ReeMapper::TypeError, "`#{name}` should be a string, got `#{truncate(value.inspect)}`"
9
+ raise ReeMapper::TypeError.new("`#{name}` should be a string, got `#{truncate(value.inspect)}`", location)
10
10
  end
11
11
  end
12
12
 
13
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => String).throws(ReeMapper::TypeError)
14
- def cast(value, name:, role: nil)
15
- serialize(value, name: name, role: role)
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)
16
16
  end
17
17
 
18
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => String).throws(ReeMapper::TypeError)
19
- def db_dump(value, name:, role: nil)
20
- serialize(value, name: name, role: role)
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)
21
21
  end
22
22
 
23
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => String).throws(ReeMapper::TypeError)
24
- def db_load(value, name:, role: nil)
25
- serialize(value, name: name, role: role)
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)
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, role: Nilor[Symbol, ArrayOf[Symbol]]] => Time).throws(ReeMapper::TypeError)
7
- def serialize(value, name:, role: nil)
6
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Time).throws(ReeMapper::TypeError)
7
+ def serialize(value, name:, location: nil)
8
8
  if value.class == Time
9
9
  value
10
10
  else
11
- raise ReeMapper::TypeError, "`#{name}` should be a time, got `#{truncate(value.inspect)}`"
11
+ raise ReeMapper::TypeError.new("`#{name}` should be a time, got `#{truncate(value.inspect)}`", location)
12
12
  end
13
13
  end
14
14
 
15
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Time).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
16
- def cast(value, name:, role: nil)
15
+ contract(Any, Kwargs[name: String, location: Nilor[String]] => Time).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
16
+ def cast(value, name:, location: nil)
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, "`#{name}` is invalid time, got `#{truncate(value.inspect)}`"
25
+ raise ReeMapper::CoercionError.new("`#{name}` is invalid time, got `#{truncate(value.inspect)}`", location)
26
26
  end
27
27
  else
28
- raise ReeMapper::TypeError, "`#{name}` should be a time, got `#{truncate(value.inspect)}`"
28
+ raise ReeMapper::TypeError.new("`#{name}` should be a time, got `#{truncate(value.inspect)}`", location)
29
29
  end
30
30
  end
31
31
 
32
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Time).throws(ReeMapper::TypeError)
33
- def db_dump(value, name:, role: nil)
34
- serialize(value, name: name, role: role)
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)
35
35
  end
36
36
 
37
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Time).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
38
- def db_load(value, name:, role: nil)
39
- cast(value, name: name, role: role)
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)
40
40
  end
41
41
  end
@@ -1,67 +1,119 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::Array < ReeMapper::AbstractWrapper
4
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]], fields_filters: ArrayOf[ReeMapper::FieldsFilter]] => Array)
5
- .throws(ReeMapper::TypeError)
6
- def serialize(value, name:, role: nil, fields_filters: [])
4
+ contract(
5
+ Any,
6
+ Kwargs[
7
+ name: String,
8
+ role: Nilor[Symbol, ArrayOf[Symbol]],
9
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
10
+ location: Nilor[String],
11
+ ] => Array
12
+ ).throws(ReeMapper::TypeError)
13
+ def serialize(value, name:, role: nil, fields_filters: [], location: nil)
7
14
  if value.is_a?(Array)
8
15
  value.map.with_index {
9
16
  if _1.nil? && subject.null
10
17
  _1
11
18
  else
12
- subject.type.serialize(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
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
+ )
13
26
  end
14
27
  }
15
28
  else
16
- raise ReeMapper::TypeError, "`#{name}` should be an array, got `#{truncate(value.inspect)}`"
29
+ raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
17
30
  end
18
31
  end
19
32
 
20
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]], fields_filters: ArrayOf[ReeMapper::FieldsFilter]] => Array)
21
- .throws(ReeMapper::TypeError)
22
- def cast(value, name:, role: nil, fields_filters: [])
33
+ contract(
34
+ Any,
35
+ Kwargs[
36
+ name: String,
37
+ role: Nilor[Symbol, ArrayOf[Symbol]],
38
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
39
+ location: Nilor[String],
40
+ ] => Array
41
+ ).throws(ReeMapper::TypeError)
42
+ def cast(value, name:, role: nil, fields_filters: [], location: nil)
23
43
  if value.is_a?(Array)
24
44
  value.map.with_index {
25
45
  if _1.nil? && subject.null
26
46
  _1
27
47
  else
28
- subject.type.cast(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
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
+ )
29
55
  end
30
56
  }
31
57
  else
32
- raise ReeMapper::TypeError, "`#{name}` should be an array, got `#{truncate(value.inspect)}`"
58
+ raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
33
59
  end
34
60
  end
35
61
 
36
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]], fields_filters: ArrayOf[ReeMapper::FieldsFilter]] => Array)
37
- .throws(ReeMapper::TypeError)
38
- def db_dump(value, name:, role: nil, fields_filters: [])
62
+ contract(
63
+ Any,
64
+ Kwargs[
65
+ name: String,
66
+ role: Nilor[Symbol, ArrayOf[Symbol]],
67
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
68
+ location: Nilor[String],
69
+ ] => Array
70
+ ).throws(ReeMapper::TypeError)
71
+ def db_dump(value, name:, role: nil, fields_filters: [], location: nil)
39
72
  if value.is_a?(Array)
40
73
  value.map.with_index {
41
74
  if _1.nil? && subject.null
42
75
  _1
43
76
  else
44
- subject.type.db_dump(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
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
+ )
45
84
  end
46
85
  }
47
86
  else
48
- raise ReeMapper::TypeError, "`#{name}` should be an array, got `#{truncate(value.inspect)}`"
87
+ raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
49
88
  end
50
89
  end
51
90
 
52
- contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]], fields_filters: ArrayOf[ReeMapper::FieldsFilter]] => Array)
53
- .throws(ReeMapper::TypeError)
54
- def db_load(value, name:, role: nil, fields_filters: [])
91
+ contract(
92
+ Any,
93
+ Kwargs[
94
+ name: String,
95
+ role: Nilor[Symbol, ArrayOf[Symbol]],
96
+ fields_filters: ArrayOf[ReeMapper::FieldsFilter],
97
+ location: Nilor[String],
98
+ ] => Array
99
+ ).throws(ReeMapper::TypeError)
100
+ def db_load(value, name:, role: nil, fields_filters: [], location: nil)
55
101
  if value.is_a?(Array)
56
102
  value.map.with_index {
57
103
  if _1.nil? && subject.null
58
104
  _1
59
105
  else
60
- subject.type.db_load(_1, name: "#{name}[#{_2}]", role: role, fields_filters: fields_filters + [subject.fields_filter])
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
+ )
61
113
  end
62
114
  }
63
115
  else
64
- raise ReeMapper::TypeError, "`#{name}` should be an array, got `#{truncate(value.inspect)}`"
116
+ raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
65
117
  end
66
118
  end
67
- end
119
+ end
@@ -14,6 +14,7 @@ module ReeMapper
14
14
 
15
15
  require_relative 'ree_mapper/types/abstract_type'
16
16
  require_relative 'ree_mapper/errors/error'
17
+ require_relative 'ree_mapper/errors/error_with_location'
17
18
  require_relative 'ree_mapper/errors/coercion_error'
18
19
  require_relative 'ree_mapper/errors/type_error'
19
20
  require_relative 'ree_mapper/errors/unsupported_type_error'
@@ -82,10 +82,12 @@ 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:, **opts)
86
- raise ReeMapper::TypeError, "`#{name}` should be a number, got `#{truncate(value.inspect)}`" if !value.is_a?(Numeric)
85
+ def serialize(value, name:, location: nil, **opts)
86
+ if !value.is_a?(Numeric)
87
+ raise ReeMapper::TypeError.new("`#{name}` should be a number, got `#{truncate(value.inspect)}`", location)
88
+ end
87
89
 
88
- subject.type.serialize(value.round, name: name, **opts)
90
+ subject.type.serialize(value.round, name: name, location: subject.location, **opts)
89
91
  end
90
92
  end
91
93
  }
@@ -100,10 +102,12 @@ RSpec.describe ReeMapper::MapperFactory do
100
102
 
101
103
  it 'allow to register caster and serializer with the same name' do
102
104
  caster_round_wrapper = Class.new(ReeMapper::AbstractWrapper) do
103
- def cast(value, name:, **opts)
104
- value = subject.type.cast(value, name: name, **opts)
105
+ def cast(value, name:, location: nil, **opts)
106
+ value = subject.type.cast(value, name: name, location: subject.location, **opts)
105
107
 
106
- raise ReeMapper::TypeError, "`#{name}` should be a number, got `#{truncate(value.inspect)}`" if !value.is_a?(Numeric)
108
+ if !value.is_a?(Numeric)
109
+ raise ReeMapper::TypeError.new("`#{name}` should be a number, got `#{truncate(value.inspect)}`", location)
110
+ end
107
111
  value.round
108
112
  end
109
113
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ package_require "ree_mapper"
2
3
 
3
4
  RSpec.describe ReeMapper::Mapper do
4
5
  link :build_mapper_factory, from: :ree_mapper
@@ -32,6 +33,12 @@ RSpec.describe ReeMapper::Mapper do
32
33
  obj.define_singleton_method(:my_field) { 1 }
33
34
  expect(mapper.cast(obj)).to eq({ my_field: 1 })
34
35
  }
36
+
37
+ it "add mapper location to error full message" do
38
+ mapper.cast({ my_field: "not number" })
39
+ rescue => e
40
+ expect(e.full_message).to include("located at")
41
+ end
35
42
  end
36
43
 
37
44
  describe 'hash dto' do
@@ -93,7 +93,8 @@ RSpec.describe 'ReeMapper::Time' do
93
93
  }
94
94
 
95
95
  it {
96
- expect { mapper.db_dump({ time: Time.new(2020).to_s }) }.to raise_error(ReeMapper::TypeError, "`time` should be a time, got `\"2020-01-01 00:00:00 +0000\"`")
96
+ time = Time.new(2020).to_s
97
+ expect { mapper.db_dump({ time: time }) }.to raise_error(ReeMapper::TypeError, "`time` should be a time, got `#{time.inspect}`")
97
98
  }
98
99
 
99
100
  it {
@@ -11,4 +11,6 @@ Bootsnap.setup(
11
11
  require 'rspec'
12
12
  require 'ree'
13
13
 
14
- Ree.init(__dir__)
14
+ ENV["RUBY_ENV"] = "test"
15
+
16
+ Ree.init(__dir__)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReeLib
4
- VERSION = "1.0.86"
4
+ VERSION = "1.0.87"
5
5
  end