active_interaction 4.0.2 → 4.0.6
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/CHANGELOG.md +40 -3
- data/README.md +6 -11
- data/lib/active_interaction/base.rb +18 -37
- data/lib/active_interaction/filter.rb +15 -0
- data/lib/active_interaction/filters/abstract_date_time_filter.rb +4 -0
- data/lib/active_interaction/filters/array_filter.rb +3 -5
- data/lib/active_interaction/filters/hash_filter.rb +1 -1
- data/lib/active_interaction/filters/interface_filter.rb +2 -1
- data/lib/active_interaction/inputs.rb +32 -47
- data/lib/active_interaction/modules/validation.rb +6 -15
- data/lib/active_interaction/version.rb +1 -1
- data/lib/active_interaction.rb +1 -0
- data/spec/active_interaction/base_spec.rb +26 -24
- data/spec/active_interaction/filters/array_filter_spec.rb +12 -8
- data/spec/active_interaction/filters/interface_filter_spec.rb +11 -0
- data/spec/active_interaction/inputs_spec.rb +32 -0
- data/spec/active_interaction/integration/hash_interaction_spec.rb +1 -1
- data/spec/spec_helper.rb +0 -6
- metadata +24 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8ea0d31fc8d2cf65540edb64cc51b1b3a31205a5f4a179fd56ecdb1606d84c9f
|
4
|
+
data.tar.gz: fd79ef266a8357bad053b282068b0fe5bfb3cf677f778b97ebe373b7c9c9a216
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4070194c1bcf654043c65e340abf6a1be0977282c214636511cb5188cace08a81a34ef811f9d3a369b7dc10a8ce8fcdda6a563c69fe34435fef6618c67dc5b7
|
7
|
+
data.tar.gz: 446e6ccc7f28132c70808817b3db99b5852486f1c097212aea861db4235da1df676c1cd3751019425a34f84b6590b9c06e954b31ae3c8dc32cf0843ea3c7d326
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,29 @@
|
|
1
|
+
# [4.0.6][] (2021-10-13)
|
2
|
+
|
3
|
+
## Fix
|
4
|
+
|
5
|
+
- [#515][] - Filters nested in arrays should accept default values as indicated in the documentation.
|
6
|
+
|
7
|
+
# [4.0.5][] (2021-07-11)
|
8
|
+
|
9
|
+
## Fix
|
10
|
+
|
11
|
+
- [#480][] - Interfaces used inside hashes failed to recognize `nil` as a non-value.
|
12
|
+
|
13
|
+
# [4.0.4][] (2021-07-03)
|
14
|
+
|
15
|
+
## Fix
|
16
|
+
|
17
|
+
- [#510][] - Hash parameters failed when working outside of Rails.
|
18
|
+
- [#511][] - Nested filters with options but no `:class` failed to have `:class` automatically added.
|
19
|
+
|
20
|
+
# [4.0.3][] (2021-06-24)
|
21
|
+
|
22
|
+
## Fix
|
23
|
+
|
24
|
+
- [#499][] - `given?` now recognizes multi-part date inputs by their primary key name
|
25
|
+
- [#493][] - `compose` now properly accepts `Inputs`
|
26
|
+
|
1
27
|
# [4.0.2][] (2021-06-22)
|
2
28
|
|
3
29
|
## Fix
|
@@ -70,7 +96,7 @@ class Example < ActiveInteraction::Base
|
|
70
96
|
|
71
97
|
validates :first_name,
|
72
98
|
presence: true,
|
73
|
-
unless:
|
99
|
+
unless: -> { first_name.nil? }
|
74
100
|
|
75
101
|
def execute
|
76
102
|
# ...
|
@@ -169,13 +195,13 @@ has a particular module included, you'll need to use the newly expanded
|
|
169
195
|
|
170
196
|
## Fixed
|
171
197
|
|
172
|
-
- [486][] `valid?` returns true if block not called and error added in execute around callback.
|
198
|
+
- [#486][] `valid?` returns true if block not called and error added in execute around callback.
|
173
199
|
|
174
200
|
# [3.8.2][] (2020-04-22)
|
175
201
|
|
176
202
|
## Fixed
|
177
203
|
|
178
|
-
- [479][] Composed interactions that throw errors now show a complete backtrace instead of ending at the `run!` of the outermost interaction.
|
204
|
+
- [#479][] Composed interactions that throw errors now show a complete backtrace instead of ending at the `run!` of the outermost interaction.
|
179
205
|
|
180
206
|
# [3.8.1][] (2020-04-04)
|
181
207
|
|
@@ -944,6 +970,10 @@ Example.run
|
|
944
970
|
|
945
971
|
- Initial release.
|
946
972
|
|
973
|
+
[4.0.6]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.5...v4.0.6
|
974
|
+
[4.0.5]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.4...v4.0.5
|
975
|
+
[4.0.4]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.3...v4.0.4
|
976
|
+
[4.0.3]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.2...v4.0.3
|
947
977
|
[4.0.2]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.1...v4.0.2
|
948
978
|
[4.0.1]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.0...v4.0.1
|
949
979
|
[4.0.0]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.3...v4.0.0
|
@@ -1153,3 +1183,10 @@ Example.run
|
|
1153
1183
|
[#398]: https://github.com/AaronLasseigne/active_interaction/issues/398
|
1154
1184
|
[#495]: https://github.com/AaronLasseigne/active_interaction/issues/495
|
1155
1185
|
[#505]: https://github.com/AaronLasseigne/active_interaction/issues/505
|
1186
|
+
[#499]: https://github.com/AaronLasseigne/active_interaction/issues/499
|
1187
|
+
[#493]: https://github.com/AaronLasseigne/active_interaction/issues/493
|
1188
|
+
[#510]: https://github.com/AaronLasseigne/active_interaction/issues/510
|
1189
|
+
[#511]: https://github.com/AaronLasseigne/active_interaction/issues/511
|
1190
|
+
[#412]: https://github.com/AaronLasseigne/active_interaction/issues/412
|
1191
|
+
[#480]: https://github.com/AaronLasseigne/active_interaction/issues/480
|
1192
|
+
[#515]: https://github.com/AaronLasseigne/active_interaction/issues/515
|
data/README.md
CHANGED
@@ -5,7 +5,6 @@ It's an implementation of the command pattern in Ruby.
|
|
5
5
|
|
6
6
|
[](https://rubygems.org/gems/active_interaction)
|
7
7
|
[](https://github.com/AaronLasseigne/active_interaction/actions?query=workflow%3ATest)
|
8
|
-
[](https://coveralls.io/r/orgsync/active_interaction)
|
9
8
|
[](https://codeclimate.com/github/orgsync/active_interaction)
|
10
9
|
|
11
10
|
---
|
@@ -58,7 +57,7 @@ handles your verbs.
|
|
58
57
|
- [Translations](#translations)
|
59
58
|
- [Credits](#credits)
|
60
59
|
|
61
|
-
[
|
60
|
+
[API Documentation][]
|
62
61
|
|
63
62
|
## Installation
|
64
63
|
|
@@ -977,10 +976,10 @@ class UpdateAccount < ActiveInteraction::Base
|
|
977
976
|
|
978
977
|
validates :first_name,
|
979
978
|
presence: true,
|
980
|
-
unless:
|
979
|
+
unless: -> { first_name.nil? }
|
981
980
|
validates :last_name,
|
982
981
|
presence: true,
|
983
|
-
unless:
|
982
|
+
unless: -> { last_name.nil? }
|
984
983
|
|
985
984
|
def execute
|
986
985
|
account.first_name = first_name if first_name.present?
|
@@ -1448,8 +1447,8 @@ I18nInteraction.run(name: false).errors.messages[:name]
|
|
1448
1447
|
|
1449
1448
|
## Credits
|
1450
1449
|
|
1451
|
-
ActiveInteraction is brought to you by [Aaron Lasseigne][]
|
1452
|
-
[Taylor Fausak][] and
|
1450
|
+
ActiveInteraction is brought to you by [Aaron Lasseigne][].
|
1451
|
+
Along with Aaron, [Taylor Fausak][] helped create and maintain ActiveInteraction but has since moved on.
|
1453
1452
|
|
1454
1453
|
If you want to contribute to ActiveInteraction, please read
|
1455
1454
|
[our contribution guidelines][]. A [complete list of contributors][] is
|
@@ -1458,14 +1457,11 @@ available on GitHub.
|
|
1458
1457
|
ActiveInteraction is licensed under [the MIT License][].
|
1459
1458
|
|
1460
1459
|
[activeinteraction]: https://github.com/AaronLasseigne/active_interaction
|
1461
|
-
[
|
1460
|
+
[API Documentation]: http://rubydoc.info/github/AaronLasseigne/active_interaction
|
1462
1461
|
[semantic versioning]: http://semver.org/spec/v2.0.0.html
|
1463
1462
|
[GitHub releases]: https://github.com/AaronLasseigne/active_interaction/releases
|
1464
|
-
[the announcement post]: http://devblog.orgsync.com/2015/05/06/announcing-active-interaction-2/
|
1465
|
-
[active_model-errors_details]: https://github.com/cowbell/active_model-errors_details
|
1466
1463
|
[aaron lasseigne]: https://github.com/AaronLasseigne
|
1467
1464
|
[taylor fausak]: https://github.com/tfausak
|
1468
|
-
[orgsync]: https://github.com/orgsync
|
1469
1465
|
[our contribution guidelines]: CONTRIBUTING.md
|
1470
1466
|
[complete list of contributors]: https://github.com/AaronLasseigne/active_interaction/graphs/contributors
|
1471
1467
|
[the mit license]: LICENSE.md
|
@@ -1474,5 +1470,4 @@ ActiveInteraction is licensed under [the MIT License][].
|
|
1474
1470
|
[the filters section]: #filters
|
1475
1471
|
[the errors section]: #errors
|
1476
1472
|
[the optional inputs section]: #optional-inputs
|
1477
|
-
[aire]: example
|
1478
1473
|
[`with_options`]: http://api.rubyonrails.org/classes/Object.html#method-i-with_options
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'active_support/core_ext/hash/indifferent_access'
|
4
|
-
|
5
3
|
module ActiveInteraction
|
6
4
|
# @abstract Subclass and override {#execute} to implement a custom
|
7
5
|
# ActiveInteraction::Base class.
|
@@ -45,7 +43,7 @@ module ActiveInteraction
|
|
45
43
|
#
|
46
44
|
# Runs validations and if there are no errors it will call {#execute}.
|
47
45
|
#
|
48
|
-
# @param (see ActiveInteraction::
|
46
|
+
# @param (see ActiveInteraction::Inputs.process)
|
49
47
|
#
|
50
48
|
# @return [Base]
|
51
49
|
|
@@ -107,7 +105,7 @@ module ActiveInteraction
|
|
107
105
|
# @param name [Symbol]
|
108
106
|
# @param options [Hash]
|
109
107
|
def add_filter(klass, name, options, &block)
|
110
|
-
raise InvalidFilterError, %("#{name}" is a reserved name) if
|
108
|
+
raise InvalidFilterError, %("#{name}" is a reserved name) if Inputs.reserved?(name)
|
111
109
|
|
112
110
|
initialize_filter(klass.new(name, options, &block))
|
113
111
|
end
|
@@ -160,12 +158,11 @@ module ActiveInteraction
|
|
160
158
|
end
|
161
159
|
end
|
162
160
|
|
163
|
-
# @param inputs [Hash{Symbol => Object}] Attribute values to set.
|
164
|
-
#
|
165
161
|
# @private
|
166
162
|
def initialize(inputs = {})
|
167
|
-
|
168
|
-
|
163
|
+
@_interaction_raw_inputs = inputs
|
164
|
+
|
165
|
+
populate_filters_and_inputs(Inputs.process(inputs))
|
169
166
|
end
|
170
167
|
|
171
168
|
# @!method compose(other, inputs = {})
|
@@ -239,20 +236,26 @@ module ActiveInteraction
|
|
239
236
|
|
240
237
|
[input, *rest].each do |key_or_index|
|
241
238
|
if key_or_index.is_a?(Symbol) || key_or_index.is_a?(String)
|
242
|
-
|
243
|
-
|
239
|
+
key = key_or_index.to_sym
|
240
|
+
key_to_s = key_or_index.to_s
|
241
|
+
filter_level = filter_level.filters[key]
|
244
242
|
|
245
243
|
break false if filter_level.nil? || input_level.nil?
|
246
|
-
|
244
|
+
if filter_level.accepts_grouped_inputs?
|
245
|
+
break false unless input_level.key?(key) || input_level.key?(key_to_s) || Inputs.keys_for_group?(input_level.keys, key)
|
246
|
+
else
|
247
|
+
break false unless input_level.key?(key) || input_level.key?(key_to_s)
|
248
|
+
end
|
247
249
|
|
248
|
-
input_level = input_level[
|
250
|
+
input_level = input_level[key] || input_level[key_to_s]
|
249
251
|
else
|
252
|
+
index = key_or_index
|
250
253
|
filter_level = filter_level.filters.first.last
|
251
254
|
|
252
255
|
break false if filter_level.nil? || input_level.nil?
|
253
|
-
break false unless
|
256
|
+
break false unless index.between?(-input_level.size, input_level.size - 1)
|
254
257
|
|
255
|
-
input_level = input_level[
|
258
|
+
input_level = input_level[index]
|
256
259
|
end
|
257
260
|
end && true
|
258
261
|
end
|
@@ -268,30 +271,8 @@ module ActiveInteraction
|
|
268
271
|
|
269
272
|
private
|
270
273
|
|
271
|
-
# We want to allow both `Hash` objects and `ActionController::Parameters`
|
272
|
-
# objects. In Rails < 5, parameters are a subclass of hash and calling
|
273
|
-
# `#symbolize_keys` returns the entire hash, not just permitted values. In
|
274
|
-
# Rails >= 5, parameters are not a subclass of hash but calling
|
275
|
-
# `#to_unsafe_h` returns the entire hash.
|
276
|
-
def normalize_inputs!(inputs)
|
277
|
-
return inputs if inputs.is_a?(Hash)
|
278
|
-
|
279
|
-
parameters = 'ActionController::Parameters'
|
280
|
-
klass = parameters.safe_constantize
|
281
|
-
return inputs.to_unsafe_h if klass && inputs.is_a?(klass)
|
282
|
-
|
283
|
-
raise ArgumentError, "inputs must be a hash or #{parameters}"
|
284
|
-
end
|
285
|
-
|
286
|
-
# @param inputs [Hash{Symbol => Object}]
|
287
|
-
def process_inputs(inputs)
|
288
|
-
@_interaction_raw_inputs = inputs
|
289
|
-
|
290
|
-
populate_filters_and_inputs(ActiveInteraction::Inputs.process(inputs))
|
291
|
-
end
|
292
|
-
|
293
274
|
def populate_filters_and_inputs(inputs)
|
294
|
-
@_interaction_inputs =
|
275
|
+
@_interaction_inputs = Inputs.new
|
295
276
|
|
296
277
|
self.class.filters.each do |name, filter|
|
297
278
|
value =
|
@@ -178,6 +178,21 @@ module ActiveInteraction
|
|
178
178
|
:string
|
179
179
|
end
|
180
180
|
|
181
|
+
# Tells whether or not the filter accepts a group of parameters to form a
|
182
|
+
# single input.
|
183
|
+
#
|
184
|
+
# @example
|
185
|
+
# ActiveInteraction::TimeFilter.new(Time.now).accepts_grouped_inputs?
|
186
|
+
# # => true
|
187
|
+
# @example
|
188
|
+
# ActiveInteraction::Filter.new(:example).accepts_grouped_inputs?
|
189
|
+
# # => false
|
190
|
+
#
|
191
|
+
# @return [Boolean]
|
192
|
+
def accepts_grouped_inputs?
|
193
|
+
false
|
194
|
+
end
|
195
|
+
|
181
196
|
private
|
182
197
|
|
183
198
|
# rubocop:disable Metrics/MethodLength
|
@@ -73,7 +73,7 @@ module ActiveInteraction
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def add_option_in_place_of_name(klass, options)
|
76
|
-
if (keys = FILTER_NAME_OR_OPTION[klass.to_s]) && (keys
|
76
|
+
if (keys = FILTER_NAME_OR_OPTION[klass.to_s]) && (keys & options.keys).empty?
|
77
77
|
options.merge(
|
78
78
|
"#{keys.first}": name.to_s.singularize.camelize.to_sym
|
79
79
|
)
|
@@ -91,7 +91,7 @@ module ActiveInteraction
|
|
91
91
|
|
92
92
|
filters[filters.size.to_s.to_sym] = filter
|
93
93
|
|
94
|
-
validate!(
|
94
|
+
validate!(names)
|
95
95
|
end
|
96
96
|
end
|
97
97
|
# rubocop:enable Style/MissingRespondToMissing
|
@@ -100,13 +100,11 @@ module ActiveInteraction
|
|
100
100
|
# @param names [Array<Symbol>]
|
101
101
|
#
|
102
102
|
# @raise [InvalidFilterError]
|
103
|
-
def validate!(
|
103
|
+
def validate!(names)
|
104
104
|
raise InvalidFilterError, 'multiple filters in array block' if filters.size > 1
|
105
105
|
|
106
106
|
raise InvalidFilterError, 'attribute names in array block' unless names.empty?
|
107
107
|
|
108
|
-
raise InvalidDefaultError, 'default values in array block' if filter.default?
|
109
|
-
|
110
108
|
nil
|
111
109
|
end
|
112
110
|
end
|
@@ -44,7 +44,7 @@ module ActiveInteraction
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def adjust_output(value, context)
|
47
|
-
value = value.to_hash
|
47
|
+
value = ActiveSupport::HashWithIndifferentAccess.new(value.to_hash)
|
48
48
|
|
49
49
|
initial = strip? ? ActiveSupport::HashWithIndifferentAccess.new : value
|
50
50
|
|
@@ -48,6 +48,7 @@ module ActiveInteraction
|
|
48
48
|
end
|
49
49
|
|
50
50
|
def matches?(object)
|
51
|
+
return false if object.nil?
|
51
52
|
return matches_methods?(object) if options.key?(:methods)
|
52
53
|
|
53
54
|
const = from
|
@@ -61,7 +62,7 @@ module ActiveInteraction
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def matches_methods?(object)
|
64
|
-
options
|
65
|
+
options[:methods].all? { |method| object.respond_to?(method) }
|
65
66
|
end
|
66
67
|
|
67
68
|
def checking_class_inheritance?(object, from)
|
@@ -13,8 +13,15 @@ module ActiveInteraction
|
|
13
13
|
/x.freeze
|
14
14
|
private_constant :GROUPED_INPUT_PATTERN
|
15
15
|
|
16
|
+
# @private
|
17
|
+
def keys_for_group?(keys, group_key)
|
18
|
+
search_key = /\A#{group_key}\(\d+i\)\z/
|
19
|
+
keys.any? { |key| search_key.match?(key) }
|
20
|
+
end
|
21
|
+
|
16
22
|
# Checking `syscall` is the result of what appears to be a bug in Ruby.
|
17
23
|
# https://bugs.ruby-lang.org/issues/15597
|
24
|
+
# @private
|
18
25
|
def reserved?(name)
|
19
26
|
name.to_s.start_with?('_interaction_') ||
|
20
27
|
name == :syscall ||
|
@@ -28,20 +35,36 @@ module ActiveInteraction
|
|
28
35
|
)
|
29
36
|
end
|
30
37
|
|
38
|
+
# @param inputs [Hash, ActionController::Parameters, ActiveInteraction::Inputs] Attribute values to set.
|
39
|
+
#
|
40
|
+
# @private
|
31
41
|
def process(inputs)
|
32
|
-
inputs
|
33
|
-
|
42
|
+
normalize_inputs!(inputs)
|
43
|
+
.stringify_keys
|
44
|
+
.sort
|
45
|
+
.each_with_object({}) do |(k, v), h|
|
46
|
+
next if reserved?(k)
|
34
47
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
48
|
+
if (group = GROUPED_INPUT_PATTERN.match(k))
|
49
|
+
assign_to_grouped_input!(h, group[:key], group[:index], v)
|
50
|
+
else
|
51
|
+
h[k.to_sym] = v
|
52
|
+
end
|
39
53
|
end
|
40
|
-
end
|
41
54
|
end
|
42
55
|
|
43
56
|
private
|
44
57
|
|
58
|
+
def normalize_inputs!(inputs)
|
59
|
+
return inputs if inputs.is_a?(Hash) || inputs.is_a?(Inputs)
|
60
|
+
|
61
|
+
parameters = 'ActionController::Parameters'
|
62
|
+
klass = parameters.safe_constantize
|
63
|
+
return inputs.to_unsafe_h if klass && inputs.is_a?(klass)
|
64
|
+
|
65
|
+
raise ArgumentError, "inputs must be a hash or #{parameters}"
|
66
|
+
end
|
67
|
+
|
45
68
|
def assign_to_grouped_input!(inputs, key, index, value)
|
46
69
|
key = key.to_sym
|
47
70
|
|
@@ -50,46 +73,8 @@ module ActiveInteraction
|
|
50
73
|
end
|
51
74
|
end
|
52
75
|
|
53
|
-
def initialize
|
54
|
-
|
55
|
-
@groups.default_proc = ->(hash, key) { hash[key] = [] }
|
56
|
-
|
57
|
-
super(@inputs = {})
|
58
|
-
end
|
59
|
-
|
60
|
-
# Associates the `value` with the `key`. Allows the `key`/`value` pair to
|
61
|
-
# be associated with one or more groups.
|
62
|
-
#
|
63
|
-
# @example
|
64
|
-
# inputs.store(:key, :value)
|
65
|
-
# # => :value
|
66
|
-
# inputs.store(:key, :value, %i[a b])
|
67
|
-
# # => :value
|
68
|
-
#
|
69
|
-
# @param key [Object] The key to store the value under.
|
70
|
-
# @param value [Object] The value to store.
|
71
|
-
# @param groups [Array<Object>] The groups to store the pair under.
|
72
|
-
#
|
73
|
-
# @return [Object] value
|
74
|
-
def store(key, value, groups = [])
|
75
|
-
groups.each do |group|
|
76
|
-
@groups[group] << key
|
77
|
-
end
|
78
|
-
|
79
|
-
super(key, value)
|
80
|
-
end
|
81
|
-
|
82
|
-
# Returns inputs from the group name given.
|
83
|
-
#
|
84
|
-
# @example
|
85
|
-
# inputs.group(:a)
|
86
|
-
# # => {key: :value}
|
87
|
-
#
|
88
|
-
# @param name [Object] Name of the group to return.
|
89
|
-
#
|
90
|
-
# @return [Hash] Inputs from the group name given.
|
91
|
-
def group(name)
|
92
|
-
@inputs.select { |k, _| @groups[name].include?(k) }
|
76
|
+
def initialize(inputs = {})
|
77
|
+
super(inputs)
|
93
78
|
end
|
94
79
|
end
|
95
80
|
end
|
@@ -14,26 +14,17 @@ module ActiveInteraction
|
|
14
14
|
filter.clean(inputs[name], context)
|
15
15
|
rescue NoDefaultError
|
16
16
|
nil
|
17
|
-
rescue InvalidNestedValueError
|
18
|
-
|
19
|
-
|
20
|
-
errors <<
|
17
|
+
rescue InvalidNestedValueError => e
|
18
|
+
errors << [filter.name, :invalid_nested, { name: e.filter_name.inspect, value: e.input_value.inspect }]
|
19
|
+
rescue InvalidValueError
|
20
|
+
errors << [filter.name, :invalid_type, { type: type(filter) }]
|
21
|
+
rescue MissingValueError
|
22
|
+
errors << [filter.name, :missing]
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
24
26
|
private
|
25
27
|
|
26
|
-
def error_args(filter, error)
|
27
|
-
case error
|
28
|
-
when InvalidNestedValueError
|
29
|
-
[filter.name, :invalid_nested, { name: error.filter_name.inspect, value: error.input_value.inspect }]
|
30
|
-
when InvalidValueError
|
31
|
-
[filter.name, :invalid_type, { type: type(filter) }]
|
32
|
-
when MissingValueError
|
33
|
-
[filter.name, :missing]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
28
|
# @param filter [Filter]
|
38
29
|
def type(filter)
|
39
30
|
I18n.translate("#{Base.i18n_scope}.types.#{filter.class.slug}")
|
data/lib/active_interaction.rb
CHANGED
@@ -46,30 +46,6 @@ describe ActiveInteraction::Base do
|
|
46
46
|
expect(interaction.instance_variable_defined?(:"@#{key}")).to be false
|
47
47
|
end
|
48
48
|
|
49
|
-
context 'with invalid inputs' do
|
50
|
-
let(:inputs) { nil }
|
51
|
-
|
52
|
-
it 'raises an error' do
|
53
|
-
expect { interaction }.to raise_error ArgumentError
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
context 'with non-hash inputs' do
|
58
|
-
let(:inputs) { [%i[k v]] }
|
59
|
-
|
60
|
-
it 'raises an error' do
|
61
|
-
expect { interaction }.to raise_error ArgumentError
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context 'with ActionController::Parameters inputs' do
|
66
|
-
let(:inputs) { ActionController::Parameters.new }
|
67
|
-
|
68
|
-
it 'does not raise an error' do
|
69
|
-
expect { interaction }.to_not raise_error
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
49
|
context 'with a filter' do
|
74
50
|
let(:described_class) { InteractionWithFilter }
|
75
51
|
|
@@ -554,6 +530,32 @@ describe ActiveInteraction::Base do
|
|
554
530
|
expect(result).to be false
|
555
531
|
end
|
556
532
|
end
|
533
|
+
|
534
|
+
context 'multi-part date values' do
|
535
|
+
let(:described_class) do
|
536
|
+
Class.new(TestInteraction) do
|
537
|
+
date :thing,
|
538
|
+
default: nil
|
539
|
+
|
540
|
+
def execute
|
541
|
+
given?(:thing)
|
542
|
+
end
|
543
|
+
end
|
544
|
+
end
|
545
|
+
|
546
|
+
it 'returns true when the input is given' do
|
547
|
+
inputs.merge!(
|
548
|
+
'thing(1i)' => '2020',
|
549
|
+
'thing(2i)' => '12',
|
550
|
+
'thing(3i)' => '31'
|
551
|
+
)
|
552
|
+
expect(result).to be true
|
553
|
+
end
|
554
|
+
|
555
|
+
it 'returns false if not found' do
|
556
|
+
expect(result).to be false
|
557
|
+
end
|
558
|
+
end
|
557
559
|
end
|
558
560
|
|
559
561
|
context 'inheritance' do
|
@@ -25,14 +25,6 @@ describe ActiveInteraction::ArrayFilter, :filter do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
context 'with a nested default' do
|
29
|
-
let(:block) { proc { array default: nil } }
|
30
|
-
|
31
|
-
it 'raises an error' do
|
32
|
-
expect { filter }.to raise_error ActiveInteraction::InvalidDefaultError
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
28
|
describe '#cast' do
|
37
29
|
let(:result) { filter.send(:cast, value, nil) }
|
38
30
|
|
@@ -137,6 +129,18 @@ describe ActiveInteraction::ArrayFilter, :filter do
|
|
137
129
|
expect(filter.filters[:'0'].options[:methods]).to eql %i[to_s]
|
138
130
|
end
|
139
131
|
end
|
132
|
+
|
133
|
+
context 'with another option set' do
|
134
|
+
let(:block) { proc { public_send(:object, converter: :new) } }
|
135
|
+
let(:name) { :objects }
|
136
|
+
|
137
|
+
it 'has a filter with the right options' do
|
138
|
+
expect(filter.filters[:'0'].options).to have_key(:class)
|
139
|
+
expect(filter.filters[:'0'].options[:class]).to eql :Object
|
140
|
+
expect(filter.filters[:'0'].options).to have_key(:converter)
|
141
|
+
expect(filter.filters[:'0'].options[:converter]).to eql :new
|
142
|
+
end
|
143
|
+
end
|
140
144
|
end
|
141
145
|
end
|
142
146
|
|
@@ -61,6 +61,17 @@ describe ActiveInteraction::InterfaceFilter, :filter do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
+
context 'that is nil' do
|
65
|
+
let(:name) { :interface_module }
|
66
|
+
let(:value) { nil }
|
67
|
+
|
68
|
+
it 'raises an error' do
|
69
|
+
expect do
|
70
|
+
result
|
71
|
+
end.to raise_error ActiveInteraction::MissingValueError
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
64
75
|
context 'with the class itself' do
|
65
76
|
let(:name) { :interface_class }
|
66
77
|
let(:value) do
|
@@ -26,6 +26,38 @@ describe ActiveInteraction::Inputs do
|
|
26
26
|
let(:inputs) { {} }
|
27
27
|
let(:result) { described_class.process(inputs) }
|
28
28
|
|
29
|
+
context 'with invalid inputs' do
|
30
|
+
let(:inputs) { nil }
|
31
|
+
|
32
|
+
it 'raises an error' do
|
33
|
+
expect { result }.to raise_error ArgumentError
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'with non-hash inputs' do
|
38
|
+
let(:inputs) { [%i[k v]] }
|
39
|
+
|
40
|
+
it 'raises an error' do
|
41
|
+
expect { result }.to raise_error ArgumentError
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'with ActionController::Parameters inputs' do
|
46
|
+
let(:inputs) { ActionController::Parameters.new }
|
47
|
+
|
48
|
+
it 'does not raise an error' do
|
49
|
+
expect { result }.to_not raise_error
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'with Inputs inputs' do
|
54
|
+
let(:inputs) { ActiveInteraction::Inputs.new }
|
55
|
+
|
56
|
+
it 'does not raise an error' do
|
57
|
+
expect { result }.to_not raise_error
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
29
61
|
context 'with simple inputs' do
|
30
62
|
before { inputs[:key] = :value }
|
31
63
|
|
@@ -19,7 +19,7 @@ describe HashInteraction do
|
|
19
19
|
before { inputs[:a] = a }
|
20
20
|
|
21
21
|
it 'returns the correct value for :a' do
|
22
|
-
expect(result[:a]).to eql a
|
22
|
+
expect(result[:a]).to eql ActiveSupport::HashWithIndifferentAccess.new(a)
|
23
23
|
end
|
24
24
|
|
25
25
|
it 'returns the correct value for :b' do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,3 @@
|
|
1
|
-
# Disable code coverage for JRuby because it always reports 0% coverage.
|
2
|
-
if RUBY_ENGINE != 'jruby'
|
3
|
-
require 'coveralls'
|
4
|
-
Coveralls.wear!
|
5
|
-
end
|
6
|
-
|
7
1
|
require 'i18n'
|
8
2
|
I18n.config.enforce_available_locales = true if I18n.config.respond_to?(:enforce_available_locales)
|
9
3
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_interaction
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0.
|
4
|
+
version: 4.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Lasseigne
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2021-
|
12
|
+
date: 2021-10-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -32,21 +32,27 @@ dependencies:
|
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '7'
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
|
-
name:
|
35
|
+
name: activesupport
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
41
|
-
|
40
|
+
version: '5'
|
41
|
+
- - "<"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '7'
|
44
|
+
type: :runtime
|
42
45
|
prerelease: false
|
43
46
|
version_requirements: !ruby/object:Gem::Requirement
|
44
47
|
requirements:
|
45
48
|
- - ">="
|
46
49
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
50
|
+
version: '5'
|
51
|
+
- - "<"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '7'
|
48
54
|
- !ruby/object:Gem::Dependency
|
49
|
-
name:
|
55
|
+
name: actionpack
|
50
56
|
requirement: !ruby/object:Gem::Requirement
|
51
57
|
requirements:
|
52
58
|
- - ">="
|
@@ -60,33 +66,33 @@ dependencies:
|
|
60
66
|
- !ruby/object:Gem::Version
|
61
67
|
version: '0'
|
62
68
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
69
|
+
name: activerecord
|
64
70
|
requirement: !ruby/object:Gem::Requirement
|
65
71
|
requirements:
|
66
|
-
- - "
|
72
|
+
- - ">="
|
67
73
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
74
|
+
version: '0'
|
69
75
|
type: :development
|
70
76
|
prerelease: false
|
71
77
|
version_requirements: !ruby/object:Gem::Requirement
|
72
78
|
requirements:
|
73
|
-
- - "
|
79
|
+
- - ">="
|
74
80
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
81
|
+
version: '0'
|
76
82
|
- !ruby/object:Gem::Dependency
|
77
|
-
name:
|
83
|
+
name: benchmark-ips
|
78
84
|
requirement: !ruby/object:Gem::Requirement
|
79
85
|
requirements:
|
80
86
|
- - "~>"
|
81
87
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
88
|
+
version: '2.7'
|
83
89
|
type: :development
|
84
90
|
prerelease: false
|
85
91
|
version_requirements: !ruby/object:Gem::Requirement
|
86
92
|
requirements:
|
87
93
|
- - "~>"
|
88
94
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
95
|
+
version: '2.7'
|
90
96
|
- !ruby/object:Gem::Dependency
|
91
97
|
name: kramdown
|
92
98
|
requirement: !ruby/object:Gem::Requirement
|
@@ -135,14 +141,14 @@ dependencies:
|
|
135
141
|
requirements:
|
136
142
|
- - "~>"
|
137
143
|
- !ruby/object:Gem::Version
|
138
|
-
version:
|
144
|
+
version: 1.17.0
|
139
145
|
type: :development
|
140
146
|
prerelease: false
|
141
147
|
version_requirements: !ruby/object:Gem::Requirement
|
142
148
|
requirements:
|
143
149
|
- - "~>"
|
144
150
|
- !ruby/object:Gem::Version
|
145
|
-
version:
|
151
|
+
version: 1.17.0
|
146
152
|
- !ruby/object:Gem::Dependency
|
147
153
|
name: rubocop-rake
|
148
154
|
requirement: !ruby/object:Gem::Requirement
|
@@ -318,7 +324,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
318
324
|
- !ruby/object:Gem::Version
|
319
325
|
version: '0'
|
320
326
|
requirements: []
|
321
|
-
rubygems_version: 3.2.
|
327
|
+
rubygems_version: 3.2.15
|
322
328
|
signing_key:
|
323
329
|
specification_version: 4
|
324
330
|
summary: Manage application specific business logic.
|