serega 0.21.0 → 0.30.0

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +113 -229
  3. data/VERSION +1 -1
  4. data/lib/serega/attribute.rb +31 -3
  5. data/lib/serega/attribute_normalizer.rb +143 -42
  6. data/lib/serega/batch/attribute_loader.rb +70 -0
  7. data/lib/serega/batch/attribute_loaders.rb +59 -0
  8. data/lib/serega/batch/auto_resolver.rb +24 -0
  9. data/lib/serega/batch/auto_resolver_factory.rb +48 -0
  10. data/lib/serega/batch/loader.rb +67 -0
  11. data/lib/serega/config.rb +59 -1
  12. data/lib/serega/object_serializer.rb +11 -9
  13. data/lib/serega/plan.rb +16 -0
  14. data/lib/serega/plan_point.rb +31 -5
  15. data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +25 -13
  16. data/lib/serega/plugins/activerecord_preloads/lib/active_record_objects.rb +31 -0
  17. data/lib/serega/plugins/camel_case/camel_case.rb +1 -1
  18. data/lib/serega/plugins/formatters/formatters.rb +79 -22
  19. data/lib/serega/plugins/if/if.rb +41 -22
  20. data/lib/serega/plugins/if/validations/check_opt_if.rb +27 -6
  21. data/lib/serega/plugins/if/validations/check_opt_if_value.rb +27 -6
  22. data/lib/serega/plugins/if/validations/check_opt_unless.rb +27 -6
  23. data/lib/serega/plugins/if/validations/check_opt_unless_value.rb +27 -6
  24. data/lib/serega/plugins/metadata/meta_attribute.rb +9 -10
  25. data/lib/serega/plugins/metadata/validations/check_block.rb +2 -4
  26. data/lib/serega/plugins/metadata/validations/check_opt_value.rb +2 -3
  27. data/lib/serega/plugins/presenter/presenter.rb +1 -1
  28. data/lib/serega/utils/format_user_preloads.rb +58 -0
  29. data/lib/serega/utils/method_signature.rb +89 -0
  30. data/lib/serega/utils/preload_paths.rb +53 -0
  31. data/lib/serega/utils/preloads_constructor.rb +77 -0
  32. data/lib/serega/validations/attribute/check_block.rb +38 -6
  33. data/lib/serega/validations/attribute/check_opt_batch.rb +101 -0
  34. data/lib/serega/validations/attribute/check_opt_const.rb +1 -0
  35. data/lib/serega/validations/attribute/check_opt_delegate.rb +1 -0
  36. data/lib/serega/validations/attribute/check_opt_method.rb +1 -0
  37. data/lib/serega/{plugins/preloads/validations → validations/attribute}/check_opt_preload.rb +2 -2
  38. data/lib/serega/{plugins/preloads/validations → validations/attribute}/check_opt_preload_path.rb +3 -3
  39. data/lib/serega/validations/attribute/check_opt_value.rb +35 -9
  40. data/lib/serega/validations/check_attribute_params.rb +3 -2
  41. data/lib/serega/validations/check_batch_loader_params.rb +80 -0
  42. data/lib/serega/validations/initiate/check_modifiers.rb +1 -1
  43. data/lib/serega.rb +98 -7
  44. metadata +17 -37
  45. data/lib/serega/plugins/batch/batch.rb +0 -168
  46. data/lib/serega/plugins/batch/lib/batch_config.rb +0 -77
  47. data/lib/serega/plugins/batch/lib/loader.rb +0 -113
  48. data/lib/serega/plugins/batch/lib/loaders.rb +0 -45
  49. data/lib/serega/plugins/batch/lib/modules/attribute.rb +0 -26
  50. data/lib/serega/plugins/batch/lib/modules/attribute_normalizer.rb +0 -78
  51. data/lib/serega/plugins/batch/lib/modules/check_attribute_params.rb +0 -22
  52. data/lib/serega/plugins/batch/lib/modules/config.rb +0 -23
  53. data/lib/serega/plugins/batch/lib/modules/object_serializer.rb +0 -46
  54. data/lib/serega/plugins/batch/lib/modules/plan_point.rb +0 -22
  55. data/lib/serega/plugins/batch/lib/plugins_extensions/activerecord_preloads.rb +0 -43
  56. data/lib/serega/plugins/batch/lib/plugins_extensions/formatters.rb +0 -54
  57. data/lib/serega/plugins/batch/lib/plugins_extensions/if.rb +0 -31
  58. data/lib/serega/plugins/batch/lib/plugins_extensions/preloads.rb +0 -34
  59. data/lib/serega/plugins/batch/lib/validations/check_batch_opt_id_method.rb +0 -43
  60. data/lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb +0 -59
  61. data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +0 -62
  62. data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +0 -60
  63. data/lib/serega/plugins/preloads/lib/modules/attribute.rb +0 -28
  64. data/lib/serega/plugins/preloads/lib/modules/attribute_normalizer.rb +0 -99
  65. data/lib/serega/plugins/preloads/lib/modules/check_attribute_params.rb +0 -22
  66. data/lib/serega/plugins/preloads/lib/modules/config.rb +0 -19
  67. data/lib/serega/plugins/preloads/lib/modules/plan_point.rb +0 -41
  68. data/lib/serega/plugins/preloads/lib/preload_paths.rb +0 -53
  69. data/lib/serega/plugins/preloads/lib/preloads_config.rb +0 -62
  70. data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +0 -79
  71. data/lib/serega/plugins/preloads/preloads.rb +0 -162
  72. data/lib/serega/utils/params_count.rb +0 -50
  73. data/lib/serega/validations/utils/check_extra_keyword_arg.rb +0 -33
@@ -1,99 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module Preloads
6
- #
7
- # Serega::SeregaAttributeNormalizer additional/patched instance methods
8
- #
9
- # @see SeregaAttributeNormalizer::AttributeNormalizerInstanceMethods
10
- #
11
- module AttributeNormalizerInstanceMethods
12
- # @return [Hash,nil] normalized attribute preloads
13
- def preloads
14
- return @preloads if instance_variable_defined?(:@preloads)
15
-
16
- @preloads = prepare_preloads
17
- end
18
-
19
- # @return [Array, nil] normalized attribute preloads path
20
- def preloads_path
21
- return @preloads_path if instance_variable_defined?(:@preloads_path)
22
-
23
- @preloads_path = prepare_preloads_path
24
- end
25
-
26
- private
27
-
28
- #
29
- # Patched in:
30
- # - plugin :batch (extension :preloads - skips auto preloads when batch option provided)
31
- #
32
- def prepare_preloads
33
- opts = init_opts
34
- preloads_provided = opts.key?(:preload)
35
- preloads =
36
- if preloads_provided
37
- opts[:preload]
38
- elsif opts.key?(:serializer) && self.class.serializer_class.config.preloads.auto_preload_attributes_with_serializer
39
- method_name
40
- elsif opts.key?(:delegate) && self.class.serializer_class.config.preloads.auto_preload_attributes_with_delegate
41
- opts[:delegate].fetch(:to)
42
- end
43
-
44
- # Nil and empty hash differs as we can preload nested results to
45
- # empty hash, but we will skip nested preloading if nil or false provided
46
- return if preloads_provided && !preloads
47
-
48
- FormatUserPreloads.call(preloads)
49
- end
50
-
51
- def prepare_preloads_path
52
- path = init_opts.fetch(:preload_path) { default_preload_path(preloads) }
53
-
54
- if path && path[0].is_a?(Array)
55
- prepare_many_preload_paths(path)
56
- else
57
- prepare_one_preload_path(path)
58
- end
59
- end
60
-
61
- def prepare_one_preload_path(path)
62
- return unless path
63
-
64
- case path
65
- when Array
66
- path.map(&:to_sym).freeze
67
- else
68
- [path.to_sym].freeze
69
- end
70
- end
71
-
72
- def prepare_many_preload_paths(paths)
73
- paths.map { |path| prepare_one_preload_path(path) }.freeze
74
- end
75
-
76
- def default_preload_path(preloads)
77
- return FROZEN_EMPTY_ARRAY if !preloads || preloads.empty?
78
-
79
- [preloads.keys.first]
80
- end
81
-
82
- #
83
- # Patch for original `prepare_hide` method
84
- # @see
85
- #
86
- # Marks attribute hidden if auto_hide_attribute_with_preloads option was set and attribute has preloads
87
- #
88
- def prepare_hide
89
- res = super
90
- return res unless res.nil?
91
-
92
- if preloads && !preloads.empty?
93
- self.class.serializer_class.config.preloads.auto_hide_attributes_with_preload || nil
94
- end
95
- end
96
- end
97
- end
98
- end
99
- end
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module Preloads
6
- #
7
- # Serega::SeregaValidations::CheckAttributeParams additional/patched class methods
8
- #
9
- # @see Serega::SeregaValidations::CheckAttributeParams
10
- #
11
- module CheckAttributeParamsInstanceMethods
12
- private
13
-
14
- def check_opts
15
- super
16
- CheckOptPreload.call(opts)
17
- CheckOptPreloadPath.call(opts)
18
- end
19
- end
20
- end
21
- end
22
- end
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module Preloads
6
- #
7
- # Config class additional/patched instance methods
8
- #
9
- # @see Serega::SeregaConfig
10
- #
11
- module ConfigInstanceMethods
12
- # @return [Serega::SeregaPlugins::Preloads::PreloadsConfig] `preloads` plugin config
13
- def preloads
14
- @preloads ||= PreloadsConfig.new(opts.fetch(:preloads))
15
- end
16
- end
17
- end
18
- end
19
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module Preloads
6
- #
7
- # Serega::SeregaPlanPoint additional/patched instance methods
8
- #
9
- # @see Serega::SeregaPlanPoint::InstanceMethods
10
- #
11
- module PlanPointInstanceMethods
12
- #
13
- # @return [Hash] preloads for nested attributes
14
- #
15
- attr_reader :preloads
16
-
17
- #
18
- # @return [Array<Symbol>] preloads path for current attribute
19
- #
20
- attr_reader :preloads_path
21
-
22
- private
23
-
24
- def set_normalized_vars
25
- super
26
-
27
- @preloads = prepare_preloads
28
- @preloads_path = prepare_preloads_path
29
- end
30
-
31
- def prepare_preloads
32
- PreloadsConstructor.call(child_plan)
33
- end
34
-
35
- def prepare_preloads_path
36
- attribute.preloads_path
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module Preloads
6
- #
7
- # Utility that helps to transform preloads to array of paths
8
- #
9
- # Example:
10
- #
11
- # call({ a: { b: { c: {}, d: {} } }, e: {} })
12
- #
13
- # => [
14
- # [:a],
15
- # [:a, :b],
16
- # [:a, :b, :c],
17
- # [:a, :b, :d],
18
- # [:e]
19
- # ]
20
- class PreloadPaths
21
- class << self
22
- #
23
- # Transforms user provided preloads to array of paths
24
- #
25
- # @param preloads [Array,Hash,String,Symbol,nil,false] association(s) to preload
26
- #
27
- # @return [Hash] preloads transformed to hash
28
- #
29
- def call(preloads)
30
- formatted_preloads = FormatUserPreloads.call(preloads)
31
- return FROZEN_EMPTY_ARRAY if formatted_preloads.empty?
32
-
33
- paths(formatted_preloads, [], [])
34
- end
35
-
36
- private
37
-
38
- def paths(formatted_preloads, path, result)
39
- formatted_preloads.each do |key, nested_preloads|
40
- path << key
41
- result << path.dup
42
-
43
- paths(nested_preloads, path, result)
44
- path.pop
45
- end
46
-
47
- result
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end
@@ -1,62 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module Preloads
6
- #
7
- # Config for `preloads` plugin
8
- #
9
- class PreloadsConfig
10
- # @return [Hash] preloads plugin options
11
- attr_reader :opts
12
-
13
- #
14
- # Initializes PreloadsConfig object
15
- #
16
- # @param opts [Hash] options
17
- #
18
- # @return [Serega::SeregaPlugins::Preloads::PreloadsConfig]
19
- #
20
- def initialize(opts)
21
- @opts = opts
22
- end
23
-
24
- # @!method auto_preload_attributes_with_delegate
25
- # @return [Boolean, nil] option value
26
- #
27
- # @!method auto_preload_attributes_with_delegate=(value)
28
- # @param value [Boolean] New option value
29
- # @return [Boolean] New option value
30
- #
31
- # @!method auto_preload_attributes_with_serializer
32
- # @return [Boolean, nil] option value
33
- #
34
- # @!method auto_preload_attributes_with_serializer=(value)
35
- # @param value [Boolean] New option value
36
- # @return [Boolean] New option value
37
- #
38
- # @!method auto_hide_attributes_with_preload
39
- # @return [Boolean, nil] option value
40
- #
41
- # @!method auto_hide_attributes_with_preload=(value)
42
- # @param value [Boolean] New option value
43
- # @return [Boolean] New option value
44
- #
45
- %i[
46
- auto_preload_attributes_with_delegate
47
- auto_preload_attributes_with_serializer
48
- auto_hide_attributes_with_preload
49
- ].each do |method_name|
50
- define_method(method_name) do
51
- opts.fetch(method_name)
52
- end
53
-
54
- define_method(:"#{method_name}=") do |value|
55
- raise SeregaError, "Must have boolean value, #{value.inspect} provided" if (value != true) && (value != false)
56
- opts[method_name] = value
57
- end
58
- end
59
- end
60
- end
61
- end
62
- end
@@ -1,79 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- module Preloads
6
- #
7
- # Finds preloads for provided attributes plan
8
- #
9
- class PreloadsConstructor
10
- class << self
11
- #
12
- # Constructs preloads hash for given attributes plan
13
- #
14
- # @param plan [Array<SeregaPlanPoint>] Serialization plan
15
- #
16
- # @return [Hash]
17
- #
18
- def call(plan)
19
- return FROZEN_EMPTY_HASH unless plan
20
-
21
- preloads = {}
22
- append_many(preloads, plan)
23
- preloads
24
- end
25
-
26
- private
27
-
28
- def append_many(preloads, plan)
29
- plan.points.each do |point|
30
- current_preloads = point.attribute.preloads
31
- next unless current_preloads
32
-
33
- child_plan = point.child_plan
34
- current_preloads = SeregaUtils::EnumDeepDup.call(current_preloads) if child_plan
35
- append_current(preloads, current_preloads)
36
- next unless child_plan
37
-
38
- each_child_preloads(preloads, point.preloads_path) do |child_preloads|
39
- append_many(child_preloads, child_plan)
40
- end
41
- end
42
- end
43
-
44
- def append_current(preloads, current_preloads)
45
- merge(preloads, current_preloads) unless current_preloads.empty?
46
- end
47
-
48
- def merge(preloads, current_preloads)
49
- preloads.merge!(current_preloads) do |_key, value_one, value_two|
50
- merge(value_one, value_two)
51
- end
52
- end
53
-
54
- def each_child_preloads(preloads, preloads_path)
55
- return yield(preloads) if preloads_path.nil?
56
-
57
- if preloads_path[0].is_a?(Array)
58
- preloads_path.each do |path|
59
- yield dig_fetch(preloads, path)
60
- end
61
- else
62
- yield dig_fetch(preloads, preloads_path)
63
- end
64
- end
65
-
66
- def dig_fetch(preloads, preloads_path)
67
- return preloads if !preloads_path || preloads_path.empty?
68
-
69
- preloads_path.each do |path|
70
- preloads = preloads.fetch(path)
71
- end
72
-
73
- preloads
74
- end
75
- end
76
- end
77
- end
78
- end
79
- end
@@ -1,162 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- #
6
- # Plugin `:preloads`
7
- #
8
- # Allows to define `:preloads` to attributes and then allows to merge preloads
9
- # from serialized attributes and return single associations hash.
10
- #
11
- # Plugin accepts options:
12
- # - `auto_preload_attributes_with_delegate` - default false
13
- # - `auto_preload_attributes_with_serializer` - default false
14
- # - `auto_hide_attributes_with_preload` - default false
15
- #
16
- # This options are very handy if you want to forget about finding preloads manually.
17
- #
18
- # Preloads can be disabled with `preload: false` attribute option.
19
- # Also automatically added preloads can be overwritten with manually specified `preload: :another_value`.
20
- #
21
- # Some examples, **please read comments in the code below**
22
- #
23
- # @example
24
- # class AppSerializer < Serega
25
- # plugin :preloads,
26
- # auto_preload_attributes_with_delegate: true,
27
- # auto_preload_attributes_with_serializer: true,
28
- # auto_hide_attributes_with_preload: true
29
- # end
30
- #
31
- # class UserSerializer < AppSerializer
32
- # # No preloads
33
- # attribute :username
34
- #
35
- # # Specify `preload: :user_stats` manually
36
- # attribute :followers_count, preload: :user_stats, value: proc { |user| user.user_stats.followers_count }
37
- #
38
- # # Automatically `preloads: :user_stats` as `auto_preload_attributes_with_delegate` option is true
39
- # attribute :comments_count, delegate: { to: :user_stats }
40
- #
41
- # # Automatically `preloads: :albums` as `auto_preload_attributes_with_serializer` option is true
42
- # attribute :albums, serializer: 'AlbumSerializer'
43
- # end
44
- #
45
- # class AlbumSerializer < AppSerializer
46
- # attribute :images_count, delegate: { to: :album_stats }
47
- # end
48
- #
49
- # # By default preloads are empty, as we specify `auto_hide_attributes_with_preload = true`,
50
- # # and attributes with preloads will be not serialized
51
- # UserSerializer.new.preloads # => {}
52
- # UserSerializer.new.to_h(OpenStruct.new(username: 'foo')) # => {:username=>"foo"}
53
- #
54
- # UserSerializer.new(with: :followers_count).preloads # => {:user_stats=>{}}
55
- # UserSerializer.new(with: %i[followers_count comments_count]).preloads # => {:user_stats=>{}}
56
- # UserSerializer.new(with: [:followers_count, :comments_count, { albums: :images_count }]).preloads # => {:user_stats=>{}, :albums=>{:album_stats=>{}}}
57
- #
58
-
59
- module Preloads
60
- DEFAULT_CONFIG = {
61
- auto_preload_attributes_with_delegate: false,
62
- auto_preload_attributes_with_serializer: false,
63
- auto_hide_attributes_with_preload: false
64
- }.freeze
65
-
66
- private_constant :DEFAULT_CONFIG
67
-
68
- # @return [Symbol] Plugin name
69
- def self.plugin_name
70
- :preloads
71
- end
72
-
73
- # Checks requirements to load plugin
74
- #
75
- # @param serializer_class [Class<Serega>] Current serializer class
76
- # @param opts [Hash] plugin options
77
- #
78
- # @return [void]
79
- #
80
- def self.before_load_plugin(serializer_class, **opts)
81
- allowed_keys = DEFAULT_CONFIG.keys
82
- opts.each_key do |key|
83
- next if allowed_keys.include?(key)
84
-
85
- raise SeregaError,
86
- "Plugin #{plugin_name.inspect} does not accept the #{key.inspect} option. Allowed options:\n" \
87
- " - :auto_preload_attributes_with_delegate [Boolean] - Automatically adds `preload: <delegate_to>` option to attributes with :delegate option specified\n" \
88
- " - :auto_preload_attributes_with_serializer [Boolean] - Automatically adds `preload: <attribute_name>` option to attributes with :serializer option specified\n" \
89
- " - :auto_hide_attributes_with_preload [Boolean] - Automatically adds `hide: true` option to attributes with :preload option (specified manually or added automatically)"
90
- end
91
-
92
- if serializer_class.plugin_used?(:batch)
93
- raise SeregaError, "Plugin #{plugin_name.inspect} must be loaded before the :batch plugin"
94
- end
95
- end
96
-
97
- #
98
- # Applies plugin code to specific serializer
99
- #
100
- # @param serializer_class [Class<Serega>] Current serializer class
101
- # @param _opts [Hash] Plugin options
102
- #
103
- # @return [void]
104
- #
105
- def self.load_plugin(serializer_class, **_opts)
106
- require_relative "lib/format_user_preloads"
107
- require_relative "lib/modules/attribute"
108
- require_relative "lib/modules/attribute_normalizer"
109
- require_relative "lib/modules/check_attribute_params"
110
- require_relative "lib/modules/config"
111
- require_relative "lib/modules/plan_point"
112
- require_relative "lib/preload_paths"
113
- require_relative "lib/preloads_config"
114
- require_relative "lib/preloads_constructor"
115
- require_relative "validations/check_opt_preload"
116
- require_relative "validations/check_opt_preload_path"
117
-
118
- serializer_class.include(InstanceMethods)
119
- serializer_class::SeregaAttribute.include(AttributeInstanceMethods)
120
- serializer_class::SeregaAttributeNormalizer.include(AttributeNormalizerInstanceMethods)
121
- serializer_class::SeregaConfig.include(ConfigInstanceMethods)
122
- serializer_class::SeregaPlanPoint.include(PlanPointInstanceMethods)
123
-
124
- serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
125
- end
126
-
127
- #
128
- # Adds config options and runs other callbacks after plugin was loaded
129
- #
130
- # @param serializer_class [Class<Serega>] Current serializer class
131
- # @param opts [Hash] Plugin options
132
- #
133
- # @return [void]
134
- #
135
- def self.after_load_plugin(serializer_class, **opts)
136
- config = serializer_class.config
137
- config.attribute_keys << :preload << :preload_path
138
-
139
- preloads_opts = DEFAULT_CONFIG.merge(opts.slice(*DEFAULT_CONFIG.keys))
140
- config.opts[:preloads] = {}
141
- preloads_config = config.preloads
142
- preloads_config.auto_preload_attributes_with_delegate = preloads_opts[:auto_preload_attributes_with_delegate]
143
- preloads_config.auto_preload_attributes_with_serializer = preloads_opts[:auto_preload_attributes_with_serializer]
144
- preloads_config.auto_hide_attributes_with_preload = preloads_opts[:auto_hide_attributes_with_preload]
145
- end
146
-
147
- #
148
- # Serega additional/patched instance methods
149
- #
150
- # @see Serega
151
- #
152
- module InstanceMethods
153
- # @return [Hash] merged preloads of all serialized attributes
154
- def preloads
155
- @preloads ||= PreloadsConstructor.call(plan)
156
- end
157
- end
158
- end
159
-
160
- register_plugin(Preloads.plugin_name, Preloads)
161
- end
162
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- #
5
- # Utilities
6
- #
7
- module SeregaUtils
8
- #
9
- # Utility to count regular parameters of callable object
10
- #
11
- class ParamsCount
12
- NO_NAMED_REST_PARAM = [:rest].freeze
13
- private_constant :NO_NAMED_REST_PARAM
14
-
15
- class << self
16
- #
17
- # Count parameters for callable object
18
- #
19
- # @param object [#call] callable object
20
- #
21
- # @return [Integer] count of regular parameters
22
- #
23
- def call(object, max_count:)
24
- # Procs (but not lambdas) can accept all provided parameters
25
- parameters = object.is_a?(Proc) ? object.parameters : object.method(:call).parameters
26
- return 1 if parameters[0] == NO_NAMED_REST_PARAM
27
- return max_count if object.is_a?(Proc) && !object.lambda?
28
-
29
- count = 0
30
-
31
- # If all we have is no-name *rest parameters, then we assume we need to provide
32
- # 1 argument. It is now always correct, but in serialization context it's most common that
33
- # only one argument is needed.
34
- parameters.each do |parameter|
35
- next if parameter == NO_NAMED_REST_PARAM # Workaround for procs like :odd?.to_proc
36
- param_type = parameter[0]
37
-
38
- case param_type
39
- when :req then count += 1
40
- when :opt then count += 1 if count < max_count
41
- when :rest then count += max_count - count if max_count > count
42
- end # else :opt, :keyreq, :key, :keyrest, :block - do nothing
43
- end
44
-
45
- count
46
- end
47
- end
48
- end
49
- end
50
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaValidations
5
- #
6
- # Validations Utilities
7
- #
8
- module Utils
9
- #
10
- # Utility to check that callable object has no required keyword arguments
11
- #
12
- class CheckExtraKeywordArg
13
- # Checks hash keys are allowed
14
- #
15
- # @param callable [#call] Callable object
16
- # @param callable_description [Symbol] Callable object description
17
- #
18
- # @raise [Serega::SeregaError] error if callable accepts required keyword argument
19
- #
20
- # @return [void]
21
- def self.call(callable, callable_description)
22
- parameters = callable.is_a?(Proc) ? callable.parameters : callable.method(:call).parameters
23
-
24
- parameters.each do |parameter|
25
- next unless parameter[0] == :keyreq
26
-
27
- raise Serega::SeregaError, "Invalid #{callable_description}. It should not have any required keyword arguments"
28
- end
29
- end
30
- end
31
- end
32
- end
33
- end