ree_lib 1.0.92 → 1.0.94

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +3 -1
  4. data/lib/ree_lib/packages/ree_actions/package/ree_actions/dsl.rb +2 -2
  5. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_array.rb +34 -26
  6. data/lib/ree_lib/packages/ree_dao/package/ree_dao/wrappers/pg_jsonb.rb +35 -25
  7. data/lib/ree_lib/packages/ree_enum/package/ree_enum/base_enum_mapper.rb +6 -18
  8. data/lib/ree_lib/packages/ree_enum/package/ree_enum/integer_value_enum_mapper.rb +6 -18
  9. data/lib/ree_lib/packages/ree_enum/package/ree_enum/string_value_enum_mapper.rb +6 -18
  10. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/errors/error_with_location.rb +47 -14
  11. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/field.rb +1 -1
  12. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/fields_filter.rb +11 -20
  13. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/mapper.rb +36 -48
  14. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/abstract_type.rb +2 -2
  15. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/any.rb +8 -8
  16. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/bool.rb +12 -12
  17. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date.rb +14 -14
  18. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date_time.rb +13 -13
  19. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/float.rb +14 -14
  20. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/integer.rb +13 -13
  21. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/rational.rb +14 -14
  22. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/string.rb +12 -12
  23. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/time.rb +13 -13
  24. data/lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/array.rb +88 -80
  25. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/benchmarks/mapper_benchmark_spec.rb +41 -1
  26. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/mapper_factory_spec.rb +17 -6
  27. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/hash_spec.rb +1 -1
  28. data/lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/type_options_spec.rb +7 -26
  29. data/lib/ree_lib/packages/ree_swagger/Package.schema.json +3 -0
  30. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_parameters.rb +2 -1
  31. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_request_body_schema.rb +12 -5
  32. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger/functions/build_serializer_schema.rb +12 -5
  33. data/lib/ree_lib/packages/ree_swagger/package/ree_swagger.rb +1 -0
  34. data/lib/ree_lib/packages/ree_swagger/schemas/ree_swagger/functions/build_parameters.schema.json +8 -0
  35. data/lib/ree_lib/packages/ree_swagger/schemas/ree_swagger/functions/build_request_body_schema.schema.json +1 -1
  36. data/lib/ree_lib/packages/ree_swagger/schemas/ree_swagger/functions/build_serializer_schema.schema.json +1 -1
  37. data/lib/ree_lib/version.rb +1 -1
  38. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b155d8bd9f9899b0f429bfbc78a4f4e039a8cc171a28ed3a50c4f21595b945c
4
- data.tar.gz: d1ef4e988d92c7aea8df9502caee87174f5433d132cca5c75e901876dec6a7b9
3
+ metadata.gz: 999bb2c56def52960bba5ba42d451d51720732b56c6133c6b2f31138fd5d1b1b
4
+ data.tar.gz: fcc8978282f0823ad26d8481c6beba74f3ff622306deabb88a93a466c6b9a476
5
5
  SHA512:
6
- metadata.gz: 373d412300c91bc3c74a746f955143694f7f6691ad461e105190c9d07417b934284b0345cab5819458c3a75894072c0241454af75e9963410d8eefba2f57a5f4
7
- data.tar.gz: ecff84e285d84523332aa2c3c66dfbc47f299a63c57a181fa36f4b8bea15913b2fa07ab66b403ba4f7eef6a28cb7e4c87b471710f4d4fca13133c8c00ea1667f
6
+ metadata.gz: cd5215c19233b1cedd2e817f7dfde0d2d034148fc548e9116f8f67b98f6678a4d7435b14119a4282840e1f20d9e87d59708e0490282b59074b2cfe38ab979c4a
7
+ data.tar.gz: d3df53d29afbcb3306437ea20e2d4fc6f36d203853737fd1d7359bc31276d744f5ad092dd4283f5ca94cf0cd36e16af1999bddacbbf2f8bd7f5776d9fe103c38
data/Gemfile CHANGED
@@ -11,4 +11,5 @@ group :test do
11
11
  gem 'rspec'
12
12
  gem 'bootsnap'
13
13
  gem 'webmock'
14
+ gem 'ruby-prof'
14
15
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.91)
4
+ ree_lib (1.0.94)
5
5
  bigdecimal (~> 3.1.6)
6
6
  binding_of_caller (~> 1.0.0)
7
7
  i18n (~> 1.14.1)
@@ -73,6 +73,7 @@ GEM
73
73
  diff-lcs (>= 1.2.0, < 2.0)
74
74
  rspec-support (~> 3.12.0)
75
75
  rspec-support (3.12.1)
76
+ ruby-prof (1.7.0)
76
77
  sequel (5.76.0)
77
78
  bigdecimal
78
79
  sqlite3 (1.4.4)
@@ -102,6 +103,7 @@ DEPENDENCIES
102
103
  roda (~> 3.76.0)
103
104
  rollbar (~> 3.5.1)
104
105
  rspec
106
+ ruby-prof
105
107
  sqlite3 (~> 1.4.4)
106
108
  timecop (~> 0.9.5)
107
109
  warden (~> 1.2.9)
@@ -44,7 +44,7 @@ module ReeActions
44
44
 
45
45
  alias_method(:__original_call, :call)
46
46
 
47
- define_method :call do |user_access, attrs|
47
+ define_method :call do |user_access, attrs, &proc|
48
48
  if self.class.const_defined?(:ActionCaster)
49
49
  caster = self.class.const_get(:ActionCaster)
50
50
 
@@ -59,7 +59,7 @@ module ReeActions
59
59
  end
60
60
  end
61
61
 
62
- __original_call(user_access, attrs)
62
+ __original_call(user_access, attrs, &proc)
63
63
  end
64
64
 
65
65
  nil
@@ -6,25 +6,29 @@ class ReeDao::PgArray < ReeMapper::AbstractWrapper
6
6
  contract(
7
7
  Any,
8
8
  Kwargs[
9
- name: String,
10
9
  role: Nilor[Symbol, ArrayOf[Symbol]],
11
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
12
- location: Nilor[String],
10
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
13
11
  ] => Or[Sequel::Postgres::PGArray, String]
14
12
  )
15
- def db_dump(value, name:, role: nil, fields_filters: [], location: nil)
13
+ def db_dump(value, role: nil, fields_filters: nil)
16
14
  if !value.is_a?(Array)
17
- raise ReeMapper::TypeError.new("`#{name}` should be an array, got `#{truncate(value.inspect)}`", location)
15
+ raise ReeMapper::TypeError.new("should be an array, got `#{truncate(value.inspect)}`")
18
16
  end
19
17
 
20
- value = value.map.with_index do |el, index|
21
- subject.type.db_dump(
22
- el,
23
- name: "#{name}[#{index}]",
24
- role: role,
25
- fields_filters: fields_filters + [subject.fields_filter],
26
- location: subject.location,
27
- )
18
+ if subject.fields_filter
19
+ fields_filters = if fields_filters
20
+ fields_filters + [subject.fields_filter]
21
+ else
22
+ [subject.fields_filter]
23
+ end
24
+ end
25
+
26
+ value = value.map.with_index do |item, idx|
27
+ subject.type.db_dump(item, role:, fields_filters:)
28
+ rescue ReeMapper::ErrorWithLocation => e
29
+ e.location ||= subject.location
30
+ e.prepend_field_name(idx.to_s)
31
+ raise e
28
32
  end
29
33
 
30
34
  if value.empty?
@@ -37,25 +41,29 @@ class ReeDao::PgArray < ReeMapper::AbstractWrapper
37
41
  contract(
38
42
  Any,
39
43
  Kwargs[
40
- name: String,
41
44
  role: Nilor[Symbol, ArrayOf[Symbol]],
42
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
43
- location: Nilor[String],
45
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
44
46
  ] => Array
45
47
  ).throws(ReeMapper::TypeError)
46
- def db_load(value, name:, role: nil, fields_filters: [], location: nil)
48
+ def db_load(value, role: nil, fields_filters: nil)
47
49
  if !value.is_a?(Sequel::Postgres::PGArray)
48
- raise ReeMapper::TypeError.new("`#{name}` should be a Sequel::Postgres::PGArray, got `#{truncate(value.inspect)}`", location)
50
+ raise ReeMapper::TypeError.new("should be a Sequel::Postgres::PGArray, got `#{truncate(value.inspect)}`")
51
+ end
52
+
53
+ if subject.fields_filter
54
+ fields_filters = if fields_filters
55
+ fields_filters + [subject.fields_filter]
56
+ else
57
+ [subject.fields_filter]
58
+ end
49
59
  end
50
60
 
51
- value.map.with_index do |val, index|
52
- subject.type.db_load(
53
- val,
54
- name: "#{name}[#{index}]",
55
- role: role,
56
- fields_filters: fields_filters + [subject.fields_filter],
57
- location: subject.location,
58
- )
61
+ value.map.with_index do |item, idx|
62
+ subject.type.db_load(item, role:, fields_filters:)
63
+ rescue ReeMapper::ErrorWithLocation => e
64
+ e.location ||= subject.location
65
+ e.prepend_field_name(idx.to_s)
66
+ raise e
59
67
  end
60
68
  end
61
69
  end
@@ -6,10 +6,8 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
6
6
  contract(
7
7
  Any,
8
8
  Kwargs[
9
- name: String,
10
9
  role: Nilor[Symbol, ArrayOf[Symbol]],
11
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
12
- location: Nilor[String],
10
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
13
11
  ] => Or[
14
12
  Sequel::Postgres::JSONBHash,
15
13
  Sequel::Postgres::JSONBArray,
@@ -21,29 +19,34 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
21
19
  Sequel::Postgres::JSONBNull
22
20
  ]
23
21
  ).throws(ReeMapper::TypeError)
24
- def db_dump(value, name:, role: nil, fields_filters: [], location: nil)
25
- value = subject.type.db_dump(
26
- value,
27
- name: name,
28
- role: role,
29
- fields_filters: fields_filters + [subject.fields_filter],
30
- location: subject.location,
31
- )
22
+ def db_dump(value, role: nil, fields_filters: nil)
23
+ if subject.fields_filter
24
+ fields_filters = if fields_filters
25
+ fields_filters + [subject.fields_filter]
26
+ else
27
+ [subject.fields_filter]
28
+ end
29
+ end
30
+
31
+ value = begin
32
+ subject.type.db_dump(value, role:, fields_filters:)
33
+ rescue ReeMapper::ErrorWithLocation => e
34
+ e.location ||= subject.location
35
+ raise e
36
+ end
32
37
 
33
38
  begin
34
39
  Sequel.pg_jsonb_wrap(value)
35
40
  rescue Sequel::Error
36
- raise ReeMapper::TypeError.new("`#{name}` should be an jsonb primitive, got `#{truncate(value.inspect)}`", location)
41
+ raise ReeMapper::TypeError.new("should be an jsonb primitive, got `#{truncate(value.inspect)}`")
37
42
  end
38
43
  end
39
44
 
40
45
  contract(
41
46
  Any,
42
47
  Kwargs[
43
- name: String,
44
48
  role: Nilor[Symbol, ArrayOf[Symbol]],
45
- fields_filters: ArrayOf[ReeMapper::FieldsFilter],
46
- location: Nilor[String],
49
+ fields_filters: Nilor[ArrayOf[ReeMapper::FieldsFilter]],
47
50
  ] => Or[
48
51
  Hash,
49
52
  Array,
@@ -55,7 +58,7 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
55
58
  Rational,
56
59
  ]
57
60
  ).throws(ReeMapper::TypeError)
58
- def db_load(value, name:, role: nil, fields_filters: [], location: nil)
61
+ def db_load(value, role: nil, fields_filters: nil)
59
62
  value = case value
60
63
  when Sequel::Postgres::JSONBHash
61
64
  ReeObject::ToHash.new.call(value.to_h)
@@ -64,15 +67,22 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
64
67
  when Numeric, String, TrueClass, FalseClass, NilClass
65
68
  value
66
69
  else
67
- raise ReeMapper::TypeError.new("`#{name}` should be a Sequel::Postgres::JSONB, got `#{truncate(value.inspect)}`", location)
70
+ raise ReeMapper::TypeError.new("should be a Sequel::Postgres::JSONB, got `#{truncate(value.inspect)}`")
68
71
  end
69
72
 
70
- subject.type.db_load(
71
- value,
72
- name: name,
73
- role: role,
74
- fields_filters: fields_filters + [subject.fields_filter],
75
- location: subject.location,
76
- )
73
+ if subject.fields_filter
74
+ fields_filters = if fields_filters
75
+ fields_filters + [subject.fields_filter]
76
+ else
77
+ [subject.fields_filter]
78
+ end
79
+ end
80
+
81
+ begin
82
+ subject.type.db_load(value, role:, fields_filters:)
83
+ rescue ReeMapper::ErrorWithLocation => e
84
+ e.location ||= subject.location
85
+ raise e
86
+ end
77
87
  end
78
- end
88
+ end
@@ -8,29 +8,17 @@ class ReeEnum::BaseEnumMapper < ReeMapper::AbstractType
8
8
  @enum = enum
9
9
  end
10
10
 
11
- contract(
12
- ReeEnum::Value,
13
- Kwargs[
14
- name: String,
15
- location: Nilor[String],
16
- ] => Or[Integer, String]
17
- )
18
- def db_dump(value, name:, location: nil)
11
+ contract(ReeEnum::Value => Or[Integer, String])
12
+ def db_dump(value)
19
13
  value.mapped_value
20
14
  end
21
15
 
22
- contract(
23
- Or[Integer, String],
24
- Kwargs[
25
- name: String,
26
- location: Nilor[String],
27
- ] => ReeEnum::Value
28
- ).throws(ReeMapper::CoercionError)
29
- def db_load(value, name:, location: nil)
16
+ contract(Or[Integer, String] => ReeEnum::Value).throws(ReeMapper::CoercionError)
17
+ def db_load(value)
30
18
  enum_val = @enum.get_values.by_mapped_value(value)
31
19
 
32
20
  if !enum_val
33
- raise ReeMapper::CoercionError.new("`#{name}` should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`", location)
21
+ raise ReeMapper::CoercionError.new("should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`")
34
22
  end
35
23
 
36
24
  enum_val
@@ -41,4 +29,4 @@ class ReeEnum::BaseEnumMapper < ReeMapper::AbstractType
41
29
  def enum_inspection
42
30
  @enum_inspection ||= truncate(@enum.get_values.each.map(&:to_s).inspect)
43
31
  end
44
- end
32
+ end
@@ -2,25 +2,13 @@
2
2
  require_relative "base_enum_mapper"
3
3
 
4
4
  class ReeEnum::IntegerValueEnumMapper < ReeEnum::BaseEnumMapper
5
- contract(
6
- ReeEnum::Value,
7
- Kwargs[
8
- name: String,
9
- location: Nilor[String],
10
- ] => Integer
11
- )
12
- def serialize(value, name:, location: nil)
5
+ contract(ReeEnum::Value => Integer)
6
+ def serialize(value)
13
7
  value.value
14
8
  end
15
9
 
16
- contract(
17
- Any,
18
- Kwargs[
19
- name: String,
20
- location: Nilor[String],
21
- ] => ReeEnum::Value
22
- ).throws(ReeMapper::CoercionError)
23
- def cast(value, name:, location: nil)
10
+ contract(Any => ReeEnum::Value).throws(ReeMapper::CoercionError)
11
+ def cast(value)
24
12
  enum_value = case value
25
13
  when Integer
26
14
  @enum.get_values.by_value(value)
@@ -34,9 +22,9 @@ class ReeEnum::IntegerValueEnumMapper < ReeEnum::BaseEnumMapper
34
22
  end
35
23
 
36
24
  if enum_value.nil?
37
- raise ReeMapper::CoercionError.new("`#{name}` should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`", location)
25
+ raise ReeMapper::CoercionError.new("should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`")
38
26
  end
39
27
 
40
28
  enum_value
41
29
  end
42
- end
30
+ end
@@ -2,25 +2,13 @@
2
2
  require_relative "base_enum_mapper"
3
3
 
4
4
  class ReeEnum::StringValueEnumMapper < ReeEnum::BaseEnumMapper
5
- contract(
6
- ReeEnum::Value,
7
- Kwargs[
8
- name: String,
9
- location: Nilor[String],
10
- ] => String
11
- )
12
- def serialize(value, name:, location: nil)
5
+ contract(ReeEnum::Value => String)
6
+ def serialize(value)
13
7
  value.value
14
8
  end
15
9
 
16
- contract(
17
- Any,
18
- Kwargs[
19
- name: String,
20
- location: Nilor[String],
21
- ] => ReeEnum::Value
22
- ).throws(ReeMapper::CoercionError)
23
- def cast(value, name:, location: nil)
10
+ contract(Any => ReeEnum::Value).throws(ReeMapper::CoercionError)
11
+ def cast(value)
24
12
  enum_value = case value
25
13
  when String
26
14
  @enum.get_values.by_value(value)
@@ -29,9 +17,9 @@ class ReeEnum::StringValueEnumMapper < ReeEnum::BaseEnumMapper
29
17
  end
30
18
 
31
19
  if enum_value.nil?
32
- raise ReeMapper::CoercionError.new("`#{name}` should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`", location)
20
+ raise ReeMapper::CoercionError.new("should be one of #{enum_inspection}, got `#{truncate(value.inspect)}`")
33
21
  end
34
22
 
35
23
  enum_value
36
24
  end
37
- end
25
+ end
@@ -1,25 +1,58 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::ErrorWithLocation < ReeMapper::Error
4
- attr_reader :location
4
+ attr_accessor :location
5
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)
6
+ contract(String, String, ArrayOf[String] => Any)
7
+ def initialize(message, location = nil, field_name_parts = [])
8
+ @message = message
12
9
  @location = location
10
+ @field_name_parts = field_name_parts
13
11
  end
14
12
 
15
- def full_message(...)
16
- msg = super
17
- return msg if location.nil?
13
+ contract(String => nil)
14
+ def prepend_field_name(part)
15
+ @field_name_parts.unshift part
16
+ nil
17
+ end
18
+
19
+ contract(None => Nilor[String])
20
+ def field_name
21
+ @field_name_parts.reduce { "#{_1}[#{_2}]" }
22
+ end
23
+
24
+ if ENV["RUBY_ENV"] == "test"
25
+
26
+ contract(None => String)
27
+ def message
28
+ msg = @message
29
+
30
+ if location
31
+ msg = "#{msg}, located at #{location}"
32
+ end
33
+
34
+ return msg if @field_name_parts.empty?
18
35
 
19
- idx = msg.index(/\).*\n/)
20
- return msg if idx.nil?
21
- return msg if ENV["RUBY_ENV"] == "test"
36
+ "`#{field_name}` #{msg}"
37
+ end
38
+
39
+ else
40
+
41
+ def message
42
+ return @message if @field_name_parts.empty?
43
+
44
+ "`#{field_name}` #{@message}"
45
+ end
46
+
47
+ def full_message(...)
48
+ msg = super
49
+ return msg if location.nil?
50
+
51
+ last_sym_idx = msg.index(/\).*\n/)
52
+ return msg if last_sym_idx.nil?
53
+
54
+ msg.insert(last_sym_idx + 1, ", located at #{location}")
55
+ end
22
56
 
23
- msg.insert(idx + 1, ", located at #{location}")
24
57
  end
25
58
  end
@@ -33,7 +33,7 @@ class ReeMapper::Field
33
33
  @roles = Array(role)
34
34
  @default = default
35
35
 
36
- @fields_filter = ReeMapper::FieldsFilter.build(only: only, except: except)
36
+ @fields_filter = ReeMapper::FieldsFilter.build(only, except)
37
37
 
38
38
  @name_as_str = @name.to_s
39
39
  @name_as_instance_var_name = :"@#{@name}"
@@ -55,35 +55,26 @@ class ReeMapper::FieldsFilter
55
55
  attr_reader :fields
56
56
  end
57
57
 
58
- class NoneStrategy
59
- def self.allow?(field)
60
- true
61
- end
62
- end
63
-
64
- def self.empty_filter
65
- @empty_filter ||= new(NoneStrategy, {}).freeze
66
- end
67
-
68
- contract Nilor[ReeMapper::FilterFieldsContract], Nilor[ReeMapper::FilterFieldsContract] => Any
69
- def self.build(only:, except:)
70
- return empty_filter if only.nil? && except.nil?
71
-
58
+ contract(
59
+ Nilor[ReeMapper::FilterFieldsContract],
60
+ Nilor[ReeMapper::FilterFieldsContract] => Nilor[ReeMapper::FieldsFilter]
61
+ )
62
+ def self.build(only, except)
72
63
  strategy = if !only.nil?
73
64
  OnlyStrategy.new(only, except)
74
65
  elsif !except.nil?
75
66
  ExceptStrategy.new(except)
76
67
  else
77
- NoneStrategy
68
+ return nil
78
69
  end
79
70
 
80
71
  nested_fields_filters = {}
81
-
72
+
82
73
  only = only&.select { _1.is_a? Hash }&.reduce(&:merge)
83
74
  except = except&.select { _1.is_a? Hash }&.reduce(&:merge)
84
75
 
85
- only&.each { nested_fields_filters[_1] = build(only: _2, except: except&.dig(_1)) }
86
- except&.each { nested_fields_filters[_1] ||= build(only: nil, except: _2) }
76
+ only&.each { nested_fields_filters[_1] = build(_2, except&.dig(_1)) }
77
+ except&.each { nested_fields_filters[_1] ||= build(nil, _2) }
87
78
 
88
79
  new(strategy, nested_fields_filters)
89
80
  end
@@ -98,9 +89,9 @@ class ReeMapper::FieldsFilter
98
89
  end
99
90
 
100
91
  def filter_for(field)
101
- nested_fields_filters.fetch(field, self.class.empty_filter)
92
+ nested_fields_filters[field]
102
93
  end
103
94
 
104
95
  private
105
96
  attr_reader :strategy, :nested_fields_filters
106
- end
97
+ end
@@ -1,8 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class ReeMapper::Mapper
4
- EMPTY_ARY = [].freeze
5
-
6
4
  contract(
7
5
  ArrayOf[ReeMapper::MapperStrategy],
8
6
  Nilor[ReeMapper::AbstractType, ReeMapper::AbstractWrapper] => self
@@ -25,77 +23,67 @@ class ReeMapper::Mapper
25
23
 
26
24
  if type
27
25
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
28
- def #{method}(obj, name: nil, role: nil, only: nil, except: nil, fields_filters: EMPTY_ARY, location: nil)
26
+ def #{method}(obj, role: nil, only: nil, except: nil, fields_filters: nil)
29
27
  #{
30
28
  if type.is_a?(ReeMapper::AbstractWrapper)
31
- "@type.#{method}(obj, name: name, role: role, fields_filters: fields_filters, location: location)"
29
+ "@type.#{method}(obj, role:, fields_filters:)"
32
30
  else
33
- "@type.#{method}(obj, name: name, location: location)"
31
+ "@type.#{method}(obj)"
34
32
  end
35
33
  }
36
34
  end
37
35
  RUBY
38
36
  else
39
37
  class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
40
- def #{method}(obj, name: nil, role: nil, only: nil, except: nil, fields_filters: EMPTY_ARY, location: nil)
41
- if only && !ReeMapper::FilterFieldsContract.valid?(only)
42
- raise ReeMapper::ArgumentError, "Invalid `only` format"
43
- end
44
-
45
- if except && !ReeMapper::FilterFieldsContract.valid?(except)
46
- raise ReeMapper::ArgumentError, "Invalid `except` format"
47
- end
38
+ def #{method}(obj, role: nil, only: nil, except: nil, fields_filters: nil)
39
+ user_fields_filter = ReeMapper::FieldsFilter.build(only, except)
48
40
 
49
- user_fields_filter = ReeMapper::FieldsFilter.build(only: only, except: except)
50
-
51
- @fields.each_with_object(@#{method}_strategy.build_object) do |(_, field), acc|
52
- field_fields_filters = if user_fields_filter == ReeMapper::FieldsFilter::NoneStrategy
53
- fields_filters
41
+ if !user_fields_filter.nil?
42
+ fields_filters = if fields_filters.nil?
43
+ [user_fields_filter]
54
44
  else
55
45
  fields_filters + [user_fields_filter]
56
46
  end
47
+ end
57
48
 
58
- next unless field_fields_filters.all? { _1.allow? field.name }
49
+ @fields.each_with_object(@#{method}_strategy.build_object) do |(_, field), acc|
50
+ next unless fields_filters.nil? || fields_filters.all? { _1.allow? field.name }
59
51
  next unless field.has_role?(role)
60
52
 
61
- is_with_value = @#{method}_strategy.has_value?(obj, field)
62
- is_optional = field.optional || @#{method}_strategy.always_optional
63
-
64
- if !is_with_value && !is_optional
65
- raise ReeMapper::TypeError.new(
66
- "Missing required field `\#{field.from_as_str}` for `\#{name || 'root'}`",
67
- field.location
68
- )
69
- end
70
-
71
- next if !is_with_value && !field.has_default?
72
-
73
- value = if is_with_value
53
+ value = if @#{method}_strategy.has_value?(obj, field)
74
54
  @#{method}_strategy.get_value(obj, field)
75
55
  else
56
+ if !field.optional && !@#{method}_strategy.always_optional
57
+ raise ReeMapper::TypeError.new(
58
+ "is missing required field",
59
+ field.location,
60
+ [field.from_as_str]
61
+ )
62
+ end
63
+
64
+ next unless field.has_default?
65
+
76
66
  field.default
77
67
  end
78
68
 
79
- unless value.nil? && field.null
80
- nested_name = name ? "\#{name}[\#{field.name_as_str}]" : field.name_as_str
69
+ if !value.nil? || !field.null
70
+ nested_fields_filters = fields_filters&.filter_map { _1.filter_for(field.name) }
81
71
 
82
- nested_fields_filters = if field_fields_filters.empty?
83
- field_fields_filters
84
- else
85
- field_fields_filters.map { _1.filter_for(field.name) }
72
+ if field.fields_filter
73
+ nested_fields_filters = if nested_fields_filters
74
+ nested_fields_filters + [field.fields_filter]
75
+ else
76
+ [field.fields_filter]
77
+ end
86
78
  end
87
79
 
88
- if field.fields_filter != ReeMapper::FieldsFilter::NoneStrategy
89
- nested_fields_filters += [field.fields_filter]
80
+ value = begin
81
+ field.type.#{method}(value, role:, fields_filters: nested_fields_filters)
82
+ rescue ReeMapper::ErrorWithLocation => e
83
+ e.prepend_field_name field.name_as_str
84
+ e.location ||= field.location
85
+ raise e
90
86
  end
91
-
92
- value = field.type.#{method}(
93
- value,
94
- name: nested_name,
95
- role: role,
96
- fields_filters: nested_fields_filters,
97
- location: field.location,
98
- )
99
87
  end
100
88
 
101
89
  @#{method}_strategy.assign_value(acc, field, value)
@@ -2,7 +2,7 @@ class ReeMapper::AbstractType
2
2
  private
3
3
 
4
4
  def truncate(str, limit = 180)
5
- @trancator ||= ReeString::Truncate.new
6
- @trancator.call(str, limit)
5
+ @truncate ||= ReeString::Truncate.new
6
+ @truncate.(str, limit)
7
7
  end
8
8
  end