active_interaction 4.0.2 → 4.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Version](https://img.shields.io/gem/v/active_interaction.svg?style=flat-square)](https://rubygems.org/gems/active_interaction)
|
7
7
|
[![Test](https://img.shields.io/github/workflow/status/AaronLasseigne/active_interaction/Test?label=Test&style=flat-square)](https://github.com/AaronLasseigne/active_interaction/actions?query=workflow%3ATest)
|
8
|
-
[![Coverage](https://img.shields.io/coveralls/github/AaronLasseigne/active_interaction.svg?style=flat-square)](https://coveralls.io/r/orgsync/active_interaction)
|
9
8
|
[![Climate](https://img.shields.io/codeclimate/maintainability/orgsync/active_interaction.svg?style=flat-square)](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.
|