serega 0.8.3 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 116b00d5c709f65a90899a9eda49f6e2c95cc9a47781a1cddf2499057553f427
4
- data.tar.gz: 5f8fe19470218be68c09704964228be0381e677f5bd3cbcf9688f92974e9392d
3
+ metadata.gz: 6b6c3672a4fc40557f4fef3e650de56c84bf23d96defabd3f3f04aa5f273aa90
4
+ data.tar.gz: 79bcc2c3526b0ae141de69003e0834c94f9b7bade028cbc85bed20c3f3ba1757
5
5
  SHA512:
6
- metadata.gz: 047de5335017cf65ee0f887124f81a755b94e19eea0e53a56ae24cb81698e7bdcc7e8eb6eba9256b5160a24bb011a5c0a1c1628cca77c7e7951b8883629ad96f
7
- data.tar.gz: 5836df28c6e1cf2238d8c8471280dc806dd41a0cbbe474a101118d801e460830cda97dcb419e0885f9106d1e4e5ae795776ff5cc475555bdab6cb4c5408c1c94
6
+ metadata.gz: edcc6856f212848b721af517bb0f77695e6e7f2adbc7bb687e4573a62efe84e02266301cc3e70647b7cd8385b96901436ce1ded9446e9712f3884d8d6348c855
7
+ data.tar.gz: e0fec25bc4471ebbf3b6fbfb1967101af7f8cd7e703cb56eba935fd51bc6de0efe87d802be8257a950648afc633ed3ceb3bfc78f67b3905197ffa0a6e39ada32
data/README.md CHANGED
@@ -20,6 +20,7 @@ It has some great features:
20
20
  - Built-in object presenter ([presenter][presenter] plugin)
21
21
  - Adding custom metadata (via [metadata][metadata] or [context_metadata][context_metadata] plugins)
22
22
  - Attributes formatters ([formatters][formatters] plugin)
23
+ - Conditional attributes ([if][if] plugin)
23
24
 
24
25
  ## Installation
25
26
 
@@ -94,9 +95,11 @@ class UserSerializer < Serega
94
95
  # It allows to specify associations to preload to attribute value
95
96
  attribute :email, preload: :emails, value: proc { |user| user.emails.find(&:verified?) }
96
97
 
97
- # Option `:hide_nil` can be specified when enabled `:hide_nil` plugin
98
- # It is literally hides attribute if its value is nil
99
- attribute :email, hide_nil: true
98
+ # Options `:if`, `:unless`, `:if_value`, `:unless_value` can be specified when enabled `:if` plugin
99
+ # They hide attribute key and value from response when conditions satisfied
100
+ # See more usage examples in :if plugin section.
101
+ attribute :email, if: proc { |user, ctx| user == ctx[:current_user] }
102
+ attribute :email, if_value: :present?
100
103
 
101
104
  # Option `:format` can be specified when enabled `:formatters` plugin
102
105
  # It changes attribute value
@@ -600,16 +603,45 @@ PostSerializer.new(with: "user(email)").to_h(post)
600
603
  PostSerializer.new(with: {user: %i[email, username]}).to_h(post)
601
604
  ```
602
605
 
603
- ### Plugin :hide_nil
606
+ ### Plugin :if
604
607
 
605
- Allows to hide attributes with `nil` values
608
+ Plugin adds `:if`, `:unless`, `:if_value`, `:unless_value` options to
609
+ attributes so we can remove attributes from response in various ways.
606
610
 
607
- ```ruby
608
- class UserSerializer < Serega
609
- plugin :hide_nil
611
+ Use `:if` and `:unless` when you want to hide attributes before finding attribute value,
612
+ and use `:if_value` and `:unless_value` to hide attributes after we find final value.
610
613
 
611
- attribute :email, hide_nil: true
612
- end
614
+ Options `:if` and `:unless` accept currently serialized object and context as parameters.
615
+ Options `:if_value` and `:unless_value` accept already found serialized value and context as parameters.
616
+
617
+ Options `:if_value` and `:unless_value` cannot be used with :serializer option, as
618
+ serialized objects have no "serialized value". Use `:if` and `:unless` in this case.
619
+
620
+ See also a `:hide` option that is available without any plugins to hide
621
+ attribute without conditions. Look at [select serialized fields](#selecting-fields) for `:hide` usage examples.
622
+
623
+ ```ruby
624
+ class UserSerializer < Serega
625
+ attribute :email, if: :active? # if user.active?
626
+ attribute :email, if: proc {|user| user.active?} # same
627
+ attribute :email, if: proc {|user, ctx| user == ctx[:current_user]} # using context
628
+ attribute :email, if: CustomPolicy.method(:view_email?) # You can provide own callable object
629
+
630
+ attribute :email, unless: :hidden? # unless user.hidden?
631
+ attribute :email, unless: proc {|user| user.hidden?} # same
632
+ attribute :email, unless: proc {|user, context| context[:show_emails]} # using context
633
+ attribute :email, unless: CustomPolicy.method(:hide_email?) # You can provide own callable object
634
+
635
+ attribute :email, if_value: :present? # if email.present?
636
+ attribute :email, if_value: proc {|email| email.present?} # same
637
+ attribute :email, if_value: proc {|email, ctx| ctx[:show_emails]} # using context
638
+ attribute :email, if_value: CustomPolicy.method(:view_email?) # You can provide own callable object
639
+
640
+ attribute :email, unless_value: :blank? # unless email.blank?
641
+ attribute :email, unless_value: proc {|email| email.blank?} # same
642
+ attribute :email, unless_value: proc {|email, context| context[:show_emails]} # using context
643
+ attribute :email, unless_value: CustomPolicy.method(:hide_email?) # You can provide own callable object
644
+ end
613
645
  ```
614
646
 
615
647
  ## Errors
@@ -648,3 +680,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
648
680
  [presenter]: #plugin-presenter
649
681
  [root]: #plugin-root
650
682
  [string_modifiers]: #plugin-string_modifiers
683
+ [if]: #plugin-if
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.3
1
+ 0.9.0
@@ -43,10 +43,14 @@ class Serega
43
43
 
44
44
  def serialize_object(object)
45
45
  points.each_with_object({}) do |point, container|
46
- attach_value(object, point, container)
46
+ serialize_point(object, point, container)
47
47
  end
48
48
  end
49
49
 
50
+ def serialize_point(object, point, container)
51
+ attach_value(object, point, container)
52
+ end
53
+
50
54
  def attach_value(object, point, container)
51
55
  value = point.value(object, context)
52
56
  final_value = final_value(value, point)
@@ -264,13 +264,17 @@ class Serega
264
264
  batch = point.batch
265
265
 
266
266
  if batch
267
- key = batch.key.call(object, context)
268
- opts[:batch_loaders].get(point, self).remember(key, container)
269
- container[point.name] = nil # Reserve attribute place in resulted hash. We will set correct value later
267
+ remember_key_for_batch_loading(batch, object, point, container)
270
268
  else
271
269
  super
272
270
  end
273
271
  end
272
+
273
+ def remember_key_for_batch_loading(batch, object, point, container)
274
+ key = batch.key.call(object, context)
275
+ opts[:batch_loaders].get(point, self).remember(key, container)
276
+ container[point.name] = nil # Reserve attribute place in resulted hash. We will set correct value later
277
+ end
274
278
  end
275
279
  end
276
280
 
@@ -0,0 +1,181 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ #
6
+ # Plugin adds `:if`, `:unless`, `:if_value`, `:unless_value` options to
7
+ # attributes so we can remove attributes from response in various ways.
8
+ #
9
+ # Use `:if` and `:unless` when you want to hide attributes before finding attribute value,
10
+ # and use `:if_value` and `:unless_value` to hide attributes after we find final value.
11
+ #
12
+ # Options `:if` and `:unless` accept currently serialized object and context as parameters.
13
+ # Options `:if_value` and `:unless_value` accept already found serialized value and context as parameters.
14
+ #
15
+ # Options `:if_value` and `:unless_value` cannot be used with :serializer option, as
16
+ # serialized objects have no "serialized value". Use `:if` and `:unless` in this case.
17
+ #
18
+ # See also a `:hide` option that is available without any plugins to hide
19
+ # attribute without conditions. Look at README.md#selecting-fields for `:hide` usage examples.
20
+ #
21
+ # Examples:
22
+ # class UserSerializer < Serega
23
+ # attribute :email, if: :active? # if user.active?
24
+ # attribute :email, if: proc {|user| user.active?} # same
25
+ # attribute :email, if: proc {|user, ctx| user == ctx[:current_user]} # using context
26
+ # attribute :email, if: CustomPolicy.method(:view_email?) # You can provide own callable object
27
+ #
28
+ # attribute :email, unless: :hidden? # unless user.hidden?
29
+ # attribute :email, unless: proc {|user| user.hidden?} # same
30
+ # attribute :email, unless: proc {|user, context| context[:show_emails]} # using context
31
+ # attribute :email, unless: CustomPolicy.method(:hide_email?) # You can provide own callable object
32
+ #
33
+ # attribute :email, if_value: :present? # if email.present?
34
+ # attribute :email, if_value: proc {|email| email.present?} # same
35
+ # attribute :email, if_value: proc {|email, ctx| ctx[:show_emails]} # using context
36
+ # attribute :email, if_value: CustomPolicy.method(:view_email?) # You can provide own callable object
37
+ #
38
+ # attribute :email, unless_value: :blank? # unless email.blank?
39
+ # attribute :email, unless_value: proc {|email| email.blank?} # same
40
+ # attribute :email, unless_value: proc {|email, context| context[:show_emails]} # using context
41
+ # attribute :email, unless_value: CustomPolicy.method(:hide_email?) # You can provide own callable object
42
+ # end
43
+ #
44
+ module If
45
+ # @return [Symbol] Plugin name
46
+ def self.plugin_name
47
+ :if
48
+ end
49
+
50
+ #
51
+ # Applies plugin code to specific serializer
52
+ #
53
+ # @param serializer_class [Class<Serega>] Current serializer class
54
+ # @param _opts [Hash] Loaded plugins options
55
+ #
56
+ # @return [void]
57
+ #
58
+ def self.load_plugin(serializer_class, **_opts)
59
+ require_relative "./validations/check_opt_if"
60
+ require_relative "./validations/check_opt_if_value"
61
+ require_relative "./validations/check_opt_unless"
62
+ require_relative "./validations/check_opt_unless_value"
63
+
64
+ serializer_class::SeregaMapPoint.include(MapPointInstanceMethods)
65
+ serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
66
+ serializer_class::SeregaObjectSerializer.include(SeregaObjectSerializerInstanceMethods)
67
+ end
68
+
69
+ # Checks requirements and loads additional plugins
70
+ #
71
+ # @param serializer_class [Class<Serega>] Current serializer class
72
+ # @param opts [Hash] loaded plugins opts
73
+ #
74
+ # @return [void]
75
+ #
76
+ def self.before_load_plugin(serializer_class, **opts)
77
+ if serializer_class.plugin_used?(:batch)
78
+ raise SeregaError, "Plugin `#{plugin_name}` must be loaded before `batch`"
79
+ end
80
+ end
81
+
82
+ #
83
+ # Adds config options and runs other callbacks after plugin was loaded
84
+ #
85
+ # @param serializer_class [Class<Serega>] Current serializer class
86
+ # @param opts [Hash] loaded plugins opts
87
+ #
88
+ # @return [void]
89
+ #
90
+ def self.after_load_plugin(serializer_class, **opts)
91
+ serializer_class.config.attribute_keys << :if << :if_value << :unless << :unless_value
92
+ end
93
+
94
+ #
95
+ # Serega::SeregaMapPoint additional/patched instance methods
96
+ #
97
+ # @see Serega::SeregaMapPoint::InstanceMethods
98
+ #
99
+ module MapPointInstanceMethods
100
+ #
101
+ # @return [Boolean] Should we show attribute or not
102
+ # Conditions for this checks are specified by :if and :unless attribute options.
103
+ #
104
+ def satisfy_if_conditions?(obj, ctx)
105
+ check_if_unless(obj, ctx, :if, :unless)
106
+ end
107
+
108
+ #
109
+ # @return [Boolean] Should we show attribute with specific value or not.
110
+ # Conditions for this checks are specified by :if_value and :unless_value attribute options.
111
+ #
112
+ def satisfy_if_value_conditions?(value, ctx)
113
+ check_if_unless(value, ctx, :if_value, :unless_value)
114
+ end
115
+
116
+ private
117
+
118
+ def check_if_unless(obj, ctx, opt_if_name, opt_unless_name)
119
+ opt_if = attribute.opts[opt_if_name]
120
+ opt_unless = attribute.opts[opt_unless_name]
121
+ return true if opt_if.nil? && opt_unless.nil?
122
+
123
+ res_if =
124
+ case opt_if
125
+ when NilClass then true
126
+ when Symbol then obj.public_send(opt_if)
127
+ else opt_if.call(obj, ctx)
128
+ end
129
+
130
+ res_unless =
131
+ case opt_unless
132
+ when NilClass then true
133
+ when Symbol then !obj.public_send(opt_unless)
134
+ else !opt_unless.call(obj, ctx)
135
+ end
136
+
137
+ res_if && res_unless
138
+ end
139
+ end
140
+
141
+ #
142
+ # Serega::SeregaValidations::CheckAttributeParams additional/patched class methods
143
+ #
144
+ # @see Serega::SeregaValidations::CheckAttributeParams
145
+ #
146
+ module CheckAttributeParamsInstanceMethods
147
+ private
148
+
149
+ def check_opts
150
+ super
151
+
152
+ CheckOptIf.call(opts)
153
+ CheckOptUnless.call(opts)
154
+ CheckOptIfValue.call(opts)
155
+ CheckOptUnlessValue.call(opts)
156
+ end
157
+ end
158
+
159
+ #
160
+ # SeregaObjectSerializer additional/patched class methods
161
+ #
162
+ # @see Serega::SeregaObjectSerializer
163
+ #
164
+ module SeregaObjectSerializerInstanceMethods
165
+ private
166
+
167
+ def serialize_point(object, point, _container)
168
+ return unless point.satisfy_if_conditions?(object, context)
169
+ super
170
+ end
171
+
172
+ def attach_final_value(value, point, _container)
173
+ return unless point.satisfy_if_value_conditions?(value, context)
174
+ super
175
+ end
176
+ end
177
+ end
178
+
179
+ register_plugin(If.plugin_name, If)
180
+ end
181
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module If
6
+ #
7
+ # Validator for attribute :if option
8
+ #
9
+ class CheckOptIf
10
+ class << self
11
+ #
12
+ # Checks attribute :if option that must be [nil, Symbol, Proc, #call]
13
+ #
14
+ # @param opts [Hash] Attribute options
15
+ #
16
+ # @raise [SeregaError] Attribute validation error
17
+ #
18
+ # @return [void]
19
+ #
20
+ def call(opts)
21
+ return unless opts.key?(:if)
22
+
23
+ check_type(opts[:if])
24
+ end
25
+
26
+ private
27
+
28
+ def check_type(value)
29
+ return if value.is_a?(Symbol)
30
+
31
+ raise SeregaError, must_be_callable unless value.respond_to?(:call)
32
+
33
+ if value.is_a?(Proc)
34
+ check_block(value)
35
+ else
36
+ check_callable(value)
37
+ end
38
+ end
39
+
40
+ def check_block(block)
41
+ return if valid_parameters?(block, accepted_count: 0..2)
42
+
43
+ raise SeregaError, block_parameters_error
44
+ end
45
+
46
+ def check_callable(callable)
47
+ return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
48
+
49
+ raise SeregaError, callable_parameters_error
50
+ end
51
+
52
+ def valid_parameters?(data, accepted_count:)
53
+ params = data.parameters
54
+ accepted_count.include?(params.count) && valid_parameters_types?(params)
55
+ end
56
+
57
+ def valid_parameters_types?(params)
58
+ params.all? do |param|
59
+ type = param[0]
60
+ (type == :req) || (type == :opt)
61
+ end
62
+ end
63
+
64
+ def block_parameters_error
65
+ "Invalid attribute option :if. When it is a Proc it can have maximum two regular parameters (object, context)"
66
+ end
67
+
68
+ def callable_parameters_error
69
+ "Invalid attribute option :if. When it is a callable object it must have two regular parameters (object, context)"
70
+ end
71
+
72
+ def must_be_callable
73
+ "Invalid attribute option :if. It must be a Symbol, a Proc or respond to :call"
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module If
6
+ #
7
+ # Validator for attribute :if_value option
8
+ #
9
+ class CheckOptIfValue
10
+ class << self
11
+ #
12
+ # Checks attribute :if_value option that must be [nil, Symbol, Proc, #call]
13
+ #
14
+ # @param opts [Hash] Attribute options
15
+ #
16
+ # @raise [SeregaError] Attribute validation error
17
+ #
18
+ # @return [void]
19
+ #
20
+ def call(opts)
21
+ return unless opts.key?(:if_value)
22
+
23
+ check_usage_with_other_params(opts)
24
+ check_type(opts[:if_value])
25
+ end
26
+
27
+ private
28
+
29
+ def check_type(value)
30
+ return if value.is_a?(Symbol)
31
+
32
+ raise SeregaError, must_be_callable unless value.respond_to?(:call)
33
+
34
+ if value.is_a?(Proc)
35
+ check_block(value)
36
+ else
37
+ check_callable(value)
38
+ end
39
+ end
40
+
41
+ def check_usage_with_other_params(opts)
42
+ raise SeregaError, "Option :if_value can not be used together with option :serializer" if opts.key?(:serializer)
43
+ end
44
+
45
+ def check_block(block)
46
+ return if valid_parameters?(block, accepted_count: 0..2)
47
+
48
+ raise SeregaError, block_parameters_error
49
+ end
50
+
51
+ def check_callable(callable)
52
+ return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
53
+
54
+ raise SeregaError, callable_parameters_error
55
+ end
56
+
57
+ def valid_parameters?(data, accepted_count:)
58
+ params = data.parameters
59
+ accepted_count.include?(params.count) && valid_parameters_types?(params)
60
+ end
61
+
62
+ def valid_parameters_types?(params)
63
+ params.all? do |param|
64
+ type = param[0]
65
+ (type == :req) || (type == :opt)
66
+ end
67
+ end
68
+
69
+ def block_parameters_error
70
+ "Invalid attribute option :if_value. When it is a Proc it can have maximum two regular parameters (object, context)"
71
+ end
72
+
73
+ def callable_parameters_error
74
+ "Invalid attribute option :if_value. When it is a callable object it must have two regular parameters (object, context)"
75
+ end
76
+
77
+ def must_be_callable
78
+ "Invalid attribute option :if_value. It must be a Symbol, a Proc or respond to :call"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module If
6
+ #
7
+ # Validator for attribute :unless option
8
+ #
9
+ class CheckOptUnless
10
+ class << self
11
+ #
12
+ # Checks attribute :unless option that must be [nil, Symbol, Proc, #call]
13
+ #
14
+ # @param opts [Hash] Attribute options
15
+ #
16
+ # @raise [SeregaError] Attribute validation error
17
+ #
18
+ # @return [void]
19
+ #
20
+ def call(opts)
21
+ return unless opts.key?(:unless)
22
+
23
+ check_type(opts[:unless])
24
+ end
25
+
26
+ private
27
+
28
+ #
29
+ # Checks attribute :unless option
30
+ #
31
+ # @param value [nil, Symbol, Proc, #call] Attribute :unless option
32
+ #
33
+ # @raise [SeregaError] validation error
34
+ #
35
+ # @return [void]
36
+ #
37
+ def check_type(value)
38
+ return if value.is_a?(Symbol)
39
+
40
+ raise SeregaError, must_be_callable unless value.respond_to?(:call)
41
+
42
+ if value.is_a?(Proc)
43
+ check_block(value)
44
+ else
45
+ check_callable(value)
46
+ end
47
+ end
48
+
49
+ def check_block(block)
50
+ return if valid_parameters?(block, accepted_count: 0..2)
51
+
52
+ raise SeregaError, block_parameters_error
53
+ end
54
+
55
+ def check_callable(callable)
56
+ return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
57
+
58
+ raise SeregaError, callable_parameters_error
59
+ end
60
+
61
+ def valid_parameters?(data, accepted_count:)
62
+ params = data.parameters
63
+ accepted_count.include?(params.count) && valid_parameters_types?(params)
64
+ end
65
+
66
+ def valid_parameters_types?(params)
67
+ params.all? do |param|
68
+ type = param[0]
69
+ (type == :req) || (type == :opt)
70
+ end
71
+ end
72
+
73
+ def block_parameters_error
74
+ "Invalid attribute option :unless. When it is a Proc it can have maximum two regular parameters (object, context)"
75
+ end
76
+
77
+ def callable_parameters_error
78
+ "Invalid attribute option :unless. When it is a callable object it must have two regular parameters (object, context)"
79
+ end
80
+
81
+ def must_be_callable
82
+ "Invalid attribute option :unless. It must be a Symbol, a Proc or respond to :call"
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Serega
4
+ module SeregaPlugins
5
+ module If
6
+ #
7
+ # Validator for attribute :unless_value option
8
+ #
9
+ class CheckOptUnlessValue
10
+ class << self
11
+ #
12
+ # Checks attribute :unless_value option that must be [nil, Symbol, Proc, #call]
13
+ #
14
+ # @param opts [Hash] Attribute options
15
+ #
16
+ # @raise [SeregaError] Attribute validation error
17
+ #
18
+ # @return [void]
19
+ #
20
+ def call(opts)
21
+ return unless opts.key?(:unless_value)
22
+
23
+ check_usage_with_other_params(opts)
24
+ check_type(opts[:unless_value])
25
+ end
26
+
27
+ private
28
+
29
+ def check_type(value)
30
+ return if value.is_a?(Symbol)
31
+
32
+ raise SeregaError, must_be_callable unless value.respond_to?(:call)
33
+
34
+ if value.is_a?(Proc)
35
+ check_block(value)
36
+ else
37
+ check_callable(value)
38
+ end
39
+ end
40
+
41
+ def check_usage_with_other_params(opts)
42
+ raise SeregaError, "Option :unless_value can not be used together with option :serializer" if opts.key?(:serializer)
43
+ end
44
+
45
+ def check_block(block)
46
+ return if valid_parameters?(block, accepted_count: 0..2)
47
+
48
+ raise SeregaError, block_parameters_error
49
+ end
50
+
51
+ def check_callable(callable)
52
+ return if valid_parameters?(callable.method(:call), accepted_count: 2..2)
53
+
54
+ raise SeregaError, callable_parameters_error
55
+ end
56
+
57
+ def valid_parameters?(data, accepted_count:)
58
+ params = data.parameters
59
+ accepted_count.include?(params.count) && valid_parameters_types?(params)
60
+ end
61
+
62
+ def valid_parameters_types?(params)
63
+ params.all? do |param|
64
+ type = param[0]
65
+ (type == :req) || (type == :opt)
66
+ end
67
+ end
68
+
69
+ def block_parameters_error
70
+ "Invalid attribute option :unless_value. When it is a Proc it can have maximum two regular parameters (object, context)"
71
+ end
72
+
73
+ def callable_parameters_error
74
+ "Invalid attribute option :unless_value. When it is a callable object it must have two regular parameters (object, context)"
75
+ end
76
+
77
+ def must_be_callable
78
+ "Invalid attribute option :unless_value. It must be a Symbol, a Proc or respond to :call"
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serega
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.3
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Glushkov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-14 00:00:00.000000000 Z
11
+ date: 2023-03-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  JSON Serializer
@@ -53,7 +53,11 @@ files:
53
53
  - lib/serega/plugins/batch/lib/validations/check_opt_batch.rb
54
54
  - lib/serega/plugins/context_metadata/context_metadata.rb
55
55
  - lib/serega/plugins/formatters/formatters.rb
56
- - lib/serega/plugins/hide_nil/hide_nil.rb
56
+ - lib/serega/plugins/if/if.rb
57
+ - lib/serega/plugins/if/validations/check_opt_if.rb
58
+ - lib/serega/plugins/if/validations/check_opt_if_value.rb
59
+ - lib/serega/plugins/if/validations/check_opt_unless.rb
60
+ - lib/serega/plugins/if/validations/check_opt_unless_value.rb
57
61
  - lib/serega/plugins/metadata/meta_attribute.rb
58
62
  - lib/serega/plugins/metadata/metadata.rb
59
63
  - lib/serega/plugins/metadata/validations/check_block.rb
@@ -115,7 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
115
119
  - !ruby/object:Gem::Version
116
120
  version: '0'
117
121
  requirements: []
118
- rubygems_version: 3.4.6
122
+ rubygems_version: 3.4.7
119
123
  signing_key:
120
124
  specification_version: 4
121
125
  summary: JSON Serializer
@@ -1,106 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Serega
4
- module SeregaPlugins
5
- #
6
- # Plugin adds `:hide_nil` option to attributes to delete them from final result
7
- # if value is nil
8
- #
9
- module HideNil
10
- # @return [Symbol] Plugin name
11
- def self.plugin_name
12
- :hide_nil
13
- end
14
-
15
- #
16
- # Applies plugin code to specific serializer
17
- #
18
- # @param serializer_class [Class<Serega>] Current serializer class
19
- # @param _opts [Hash] Loaded plugins options
20
- #
21
- # @return [void]
22
- #
23
- def self.load_plugin(serializer_class, **_opts)
24
- serializer_class::SeregaAttribute.include(AttributeInstanceMethods)
25
- serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
26
- serializer_class::SeregaObjectSerializer.include(SeregaObjectSerializerInstanceMethods)
27
- end
28
-
29
- #
30
- # Adds config options and runs other callbacks after plugin was loaded
31
- #
32
- # @param serializer_class [Class<Serega>] Current serializer class
33
- # @param opts [Hash] loaded plugins opts
34
- #
35
- # @return [void]
36
- #
37
- def self.after_load_plugin(serializer_class, **opts)
38
- serializer_class.config.attribute_keys << :hide_nil
39
- end
40
-
41
- #
42
- # Serega::SeregaAttribute additional/patched instance methods
43
- #
44
- # @see Serega::SeregaValidations::CheckAttributeParams
45
- #
46
- module AttributeInstanceMethods
47
- # Check hide_nil is specified
48
- def hide_nil?
49
- !!opts[:hide_nil]
50
- end
51
- end
52
-
53
- #
54
- # Serega::SeregaValidations::CheckAttributeParams additional/patched class methods
55
- #
56
- # @see Serega::SeregaValidations::CheckAttributeParams
57
- #
58
- module CheckAttributeParamsInstanceMethods
59
- private
60
-
61
- def check_opts
62
- super
63
- CheckOptHideNil.call(opts)
64
- end
65
- end
66
-
67
- #
68
- # Validator class for :hide_nil attribute option
69
- #
70
- class CheckOptHideNil
71
- #
72
- # Checks attribute :hide_nil option
73
- #
74
- # @param opts [Hash] Attribute options
75
- #
76
- # @raise [Serega::SeregaError] SeregaError that option has invalid value
77
- #
78
- # @return [void]
79
- #
80
- def self.call(opts)
81
- return unless opts.key?(:hide_nil)
82
-
83
- value = opts[:hide_nil]
84
- return if (value == true) || (value == false)
85
-
86
- raise SeregaError, "Invalid option :hide_nil => #{value.inspect}. Must have a boolean value"
87
- end
88
- end
89
-
90
- #
91
- # SeregaObjectSerializer additional/patched class methods
92
- #
93
- # @see Serega::SeregaObjectSerializer
94
- #
95
- module SeregaObjectSerializerInstanceMethods
96
- private
97
-
98
- def attach_final_value(final_value, *)
99
- super unless final_value.nil?
100
- end
101
- end
102
- end
103
-
104
- register_plugin(HideNil.plugin_name, HideNil)
105
- end
106
- end