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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b6d048d5a1bc4790a7852753a5bb79b74ddcef73e88603692fc0c580a28247c
4
- data.tar.gz: 62091b8494eee0cd2d90b64fb9540067e0b98446403af42e21ddb45df2891f9c
3
+ metadata.gz: 8ea0d31fc8d2cf65540edb64cc51b1b3a31205a5f4a179fd56ecdb1606d84c9f
4
+ data.tar.gz: fd79ef266a8357bad053b282068b0fe5bfb3cf677f778b97ebe373b7c9c9a216
5
5
  SHA512:
6
- metadata.gz: bf7ba20068a6d5aee70730136d891d1bc4ce94d49ec8d7558805e3c6e017ba8560943581c31a99760890572a5b8d4121ec4ec8c8d639c3a29878505d56f09221
7
- data.tar.gz: 12a9fb539e434435065fde8671905b34fa742e4ebe5b030992b2d0ed58c17040cbaa9b2125a7a391311bd64659aa24416aa6c2d2b3ab151cadde018be1ff86fb
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: 'first_name.nil?'
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
- [Full Documentation][]
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: 'first_name.nil?'
979
+ unless: -> { first_name.nil? }
981
980
  validates :last_name,
982
981
  presence: true,
983
- unless: 'last_name.nil?'
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][] and
1452
- [Taylor Fausak][] and was originally built at [OrgSync][].
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
- [Full Documentation]: http://rubydoc.info/github/orgsync/active_interaction
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::Base#initialize)
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 ActiveInteraction::Inputs.reserved?(name)
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
- inputs = normalize_inputs!(inputs)
168
- process_inputs(inputs.symbolize_keys)
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
- key_or_index = key_or_index.to_sym
243
- filter_level = filter_level.filters[key_or_index]
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
- break false unless input_level.key?(key_or_index) || input_level.key?(key_or_index.to_s)
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[key_or_index] || input_level[key_or_index.to_s]
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 key_or_index.between?(-input_level.size, input_level.size - 1)
256
+ break false unless index.between?(-input_level.size, input_level.size - 1)
254
257
 
255
- input_level = input_level[key_or_index]
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 = ActiveInteraction::Inputs.new
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
@@ -12,6 +12,10 @@ module ActiveInteraction
12
12
  self.class.slug
13
13
  end
14
14
 
15
+ def accepts_grouped_inputs?
16
+ true
17
+ end
18
+
15
19
  private
16
20
 
17
21
  def klasses
@@ -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 && options.keys).empty?
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!(filter, names)
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!(filter, names)
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.with_indifferent_access
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.fetch(:methods, []).all? { |method| object.respond_to?(method) }
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.stringify_keys.sort.each_with_object({}) do |(k, v), h|
33
- next if reserved?(k)
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
- if (group = GROUPED_INPUT_PATTERN.match(k))
36
- assign_to_grouped_input!(h, group[:key], group[:index], v)
37
- else
38
- h[k.to_sym] = v
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
- @groups = {}
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
- InvalidValueError,
19
- MissingValueError => e
20
- errors << error_args(filter, e)
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}")
@@ -4,5 +4,5 @@ module ActiveInteraction
4
4
  # The version number.
5
5
  #
6
6
  # @return [Gem::Version]
7
- VERSION = Gem::Version.new('4.0.2')
7
+ VERSION = Gem::Version.new('4.0.6')
8
8
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_model'
4
+ require 'active_support/hash_with_indifferent_access'
4
5
 
5
6
  # Manage application specific business logic.
6
7
  #
@@ -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.with_indifferent_access
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.2
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-06-22 00:00:00.000000000 Z
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: actionpack
35
+ name: activesupport
36
36
  requirement: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
41
- type: :development
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: '0'
50
+ version: '5'
51
+ - - "<"
52
+ - !ruby/object:Gem::Version
53
+ version: '7'
48
54
  - !ruby/object:Gem::Dependency
49
- name: activerecord
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: benchmark-ips
69
+ name: activerecord
64
70
  requirement: !ruby/object:Gem::Requirement
65
71
  requirements:
66
- - - "~>"
72
+ - - ">="
67
73
  - !ruby/object:Gem::Version
68
- version: '2.7'
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: '2.7'
81
+ version: '0'
76
82
  - !ruby/object:Gem::Dependency
77
- name: coveralls
83
+ name: benchmark-ips
78
84
  requirement: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - "~>"
81
87
  - !ruby/object:Gem::Version
82
- version: '0.8'
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: '0.8'
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: '1.8'
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: '1.8'
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.3
327
+ rubygems_version: 3.2.15
322
328
  signing_key:
323
329
  specification_version: 4
324
330
  summary: Manage application specific business logic.