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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/Gemfile.lock +28 -23
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_array.rb +12 -8
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_jsonb.rb +12 -8
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_array_spec.rb +3 -3
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/wrappers/pg_jsonb_spec.rb +4 -4
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/base_enum_mapper.rb +5 -5
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/integer_value_enum_mapper.rb +5 -5
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/string_value_enum_mapper.rb +5 -5
- data/lib/ree_lib/packages/ree_enum/spec/ree_enum/dsl_spec.rb +3 -3
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/coercion_error.rb +1 -1
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/error_with_location.rb +25 -0
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/type_error.rb +1 -1
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/field.rb +12 -4
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +12 -6
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper_factory.rb +17 -4
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +8 -8
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/bool.rb +12 -12
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date.rb +13 -13
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date_time.rb +13 -13
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/float.rb +13 -13
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/integer.rb +13 -13
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/rational.rb +13 -13
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/string.rb +12 -12
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/time.rb +13 -13
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/array.rb +73 -21
- data/lib/ree_lib/packages/ree_mapper/package/ree_mapper.rb +1 -0
- data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +10 -6
- data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_spec.rb +7 -0
- data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/time_spec.rb +2 -1
- data/lib/ree_lib/spec.init.rb +3 -1
- data/lib/ree_lib/version.rb +1 -1
- 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,
|
|
8
|
-
def serialize(value, name:,
|
|
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
|
|
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,
|
|
17
|
-
def cast(value, name:,
|
|
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
|
|
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,
|
|
28
|
-
def db_dump(value, name:,
|
|
29
|
-
serialize(value, name: name,
|
|
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,
|
|
33
|
-
def db_load(value, name:,
|
|
34
|
-
cast(value, name: name,
|
|
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,
|
|
7
|
-
def serialize(value, name:,
|
|
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
|
|
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,
|
|
16
|
-
def cast(value, name:,
|
|
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
|
|
25
|
+
raise ReeMapper::CoercionError.new("`#{name}` is invalid date, got `#{truncate(value.inspect)}`", location)
|
|
26
26
|
end
|
|
27
27
|
else
|
|
28
|
-
raise ReeMapper::TypeError
|
|
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,
|
|
33
|
-
def db_dump(value, name:,
|
|
34
|
-
serialize(value, name: name,
|
|
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,
|
|
38
|
-
def db_load(value, name:,
|
|
39
|
-
cast(value, name: name,
|
|
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,
|
|
7
|
-
def serialize(value, name:,
|
|
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
|
|
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,
|
|
16
|
-
def cast(value, name:,
|
|
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
|
|
25
|
+
raise ReeMapper::CoercionError.new("`#{name}` is invalid datetime, got `#{truncate(value.inspect)}`", location)
|
|
26
26
|
end
|
|
27
27
|
else
|
|
28
|
-
raise ReeMapper::TypeError
|
|
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,
|
|
33
|
-
def db_dump(value, name:,
|
|
34
|
-
serialize(value, name: name,
|
|
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,
|
|
38
|
-
def db_load(value, name:,
|
|
39
|
-
cast(value, name: name,
|
|
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,
|
|
5
|
-
def serialize(value, name:,
|
|
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
|
|
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,
|
|
14
|
-
def cast(value, name:,
|
|
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
|
|
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
|
|
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,
|
|
31
|
-
def db_dump(value, name:,
|
|
32
|
-
serialize(value, name: name,
|
|
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,
|
|
36
|
-
def db_load(value, name:,
|
|
37
|
-
cast(value, name: name,
|
|
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,
|
|
5
|
-
def serialize(value, name:,
|
|
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
|
|
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
|
|
14
|
-
def cast(value, name:,
|
|
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
|
|
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
|
|
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,
|
|
29
|
-
def db_dump(value, name:,
|
|
30
|
-
serialize(value, name: name,
|
|
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,
|
|
34
|
-
def db_load(value, name:,
|
|
35
|
-
cast(value, name: name,
|
|
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,
|
|
5
|
-
def serialize(value, name:,
|
|
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
|
|
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,
|
|
14
|
-
def cast(value, name:,
|
|
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
|
|
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
|
|
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,
|
|
31
|
-
def db_dump(value, name:,
|
|
32
|
-
serialize(value, name: name,
|
|
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,
|
|
36
|
-
def db_load(value, name:,
|
|
37
|
-
cast(value, name: name,
|
|
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,
|
|
5
|
-
def serialize(value, name:,
|
|
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
|
|
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,
|
|
14
|
-
def cast(value, name:,
|
|
15
|
-
serialize(value, name: name,
|
|
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,
|
|
19
|
-
def db_dump(value, name:,
|
|
20
|
-
serialize(value, name: name,
|
|
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,
|
|
24
|
-
def db_load(value, name:,
|
|
25
|
-
serialize(value, name: name,
|
|
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,
|
|
7
|
-
def serialize(value, name:,
|
|
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
|
|
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,
|
|
16
|
-
def cast(value, name:,
|
|
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
|
|
25
|
+
raise ReeMapper::CoercionError.new("`#{name}` is invalid time, got `#{truncate(value.inspect)}`", location)
|
|
26
26
|
end
|
|
27
27
|
else
|
|
28
|
-
raise ReeMapper::TypeError
|
|
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,
|
|
33
|
-
def db_dump(value, name:,
|
|
34
|
-
serialize(value, name: name,
|
|
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,
|
|
38
|
-
def db_load(value, name:,
|
|
39
|
-
cast(value, name: name,
|
|
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(
|
|
5
|
-
|
|
6
|
-
|
|
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(
|
|
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
|
|
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(
|
|
21
|
-
|
|
22
|
-
|
|
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(
|
|
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
|
|
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(
|
|
37
|
-
|
|
38
|
-
|
|
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(
|
|
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
|
|
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(
|
|
53
|
-
|
|
54
|
-
|
|
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(
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
data/lib/ree_lib/spec.init.rb
CHANGED
data/lib/ree_lib/version.rb
CHANGED