active_interaction 3.5.0 → 3.6.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 +4 -4
- data/README.md +59 -6
- data/lib/active_interaction/base.rb +6 -9
- data/lib/active_interaction/errors.rb +6 -8
- data/lib/active_interaction/filters/object_filter.rb +45 -5
- data/lib/active_interaction/filters/record_filter.rb +88 -0
- data/lib/active_interaction/locale/en.yml +1 -0
- data/lib/active_interaction/locale/fr.yml +1 -0
- data/lib/active_interaction/locale/pt-BR.yml +1 -0
- data/lib/active_interaction/modules/input_processor.rb +3 -3
- data/lib/active_interaction/version.rb +1 -1
- data/lib/active_interaction.rb +1 -0
- data/spec/active_interaction/base_spec.rb +15 -13
- data/spec/active_interaction/errors_spec.rb +13 -1
- data/spec/active_interaction/filters/object_filter_spec.rb +137 -30
- data/spec/active_interaction/filters/record_filter_spec.rb +210 -0
- data/spec/active_interaction/i18n_spec.rb +2 -1
- data/spec/active_interaction/modules/input_processor_spec.rb +2 -4
- data/spec/support/interactions.rb +8 -4
- metadata +39 -36
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f61c20e8e7ee4f4f1d84d6244f11e4efae82a8b6
|
|
4
|
+
data.tar.gz: 5164aa102d888aa3405cf66be6b7a72a809fac83
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 36e0b36fed1473f0a3c4f3a5008d6a8bb40186923b20122570f8df517c82495d6cfd9fdceea6c5924dbb481b62461f19f9447152d1d1f6f8a499c9935f85312a
|
|
7
|
+
data.tar.gz: cd74144ec70e28fc1c23fc530edf2195e275333838fed2f22037bb838cf5aaf8323cfb80a984feb0bc23e4c11cbd62352a915c10fc0dc380ac82fcf74c2ba38c
|
data/README.md
CHANGED
|
@@ -28,6 +28,7 @@ Read more on [the project page][] or check out [the full documentation][].
|
|
|
28
28
|
- [Hash](#hash)
|
|
29
29
|
- [Interface](#interface)
|
|
30
30
|
- [Object](#object)
|
|
31
|
+
- [Record](#record)
|
|
31
32
|
- [String](#string)
|
|
32
33
|
- [Symbol](#symbol)
|
|
33
34
|
- [Dates and times](#dates-and-times)
|
|
@@ -66,13 +67,13 @@ Read more on [the project page][] or check out [the full documentation][].
|
|
|
66
67
|
Add it to your Gemfile:
|
|
67
68
|
|
|
68
69
|
``` rb
|
|
69
|
-
gem 'active_interaction', '~> 3.
|
|
70
|
+
gem 'active_interaction', '~> 3.6'
|
|
70
71
|
```
|
|
71
72
|
|
|
72
73
|
Or install it manually:
|
|
73
74
|
|
|
74
75
|
``` sh
|
|
75
|
-
$ gem install active_interaction --version '~> 3.
|
|
76
|
+
$ gem install active_interaction --version '~> 3.6'
|
|
76
77
|
```
|
|
77
78
|
|
|
78
79
|
This project uses [Semantic Versioning][]. Check out [GitHub releases][] for a
|
|
@@ -418,6 +419,61 @@ object :dolly3,
|
|
|
418
419
|
class: :Sheep
|
|
419
420
|
```
|
|
420
421
|
|
|
422
|
+
If you have value objects or you would like to build one object from another,
|
|
423
|
+
you can use the `converter` option. It is only called if the value provided does
|
|
424
|
+
not pass `#is_a?` and `.===` for the object class. The `converter` option
|
|
425
|
+
accepts a symbol that specifies a class method on the object class or a proc.
|
|
426
|
+
Both will be passed the value and any errors thrown inside the converter will
|
|
427
|
+
cause the value to be considered invalid. Any returned value that is not the
|
|
428
|
+
correct class will also be treated as invalid. The value given to the `default`
|
|
429
|
+
option will also be converted.
|
|
430
|
+
|
|
431
|
+
``` rb
|
|
432
|
+
class ObjectInteraction < ActiveInteraction::Base
|
|
433
|
+
object :ip_address,
|
|
434
|
+
class: IPAddr,
|
|
435
|
+
converter: :new
|
|
436
|
+
|
|
437
|
+
def execute
|
|
438
|
+
ip_address
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
ObjectInteraction.run!(ip_address: '192.168.1.1')
|
|
443
|
+
# #<IPAddr: IPv4:192.168.1.1/255.255.255.255>
|
|
444
|
+
|
|
445
|
+
ObjectInteraction.run!(ip_address: 1)
|
|
446
|
+
# ActiveInteraction::InvalidInteractionError: Ip address is not a valid object
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Record
|
|
450
|
+
|
|
451
|
+
Record filters allow you to require an instance of a particular class or a value
|
|
452
|
+
that can be used to locate an instance of the object. It checks either `#is_a?`
|
|
453
|
+
on the instance or `.===` on the class. If the value does not match, it will
|
|
454
|
+
call `find` on the class of the record. This is particularly useful when working
|
|
455
|
+
with ActiveRecord objects. Like an object filter, the class is derived from the
|
|
456
|
+
name passed but can be specified with the `class` option. The value given to the
|
|
457
|
+
`default` option will also be found.
|
|
458
|
+
|
|
459
|
+
``` rb
|
|
460
|
+
class RecordInteraction < ActiveInteraction::Base
|
|
461
|
+
record :encoding
|
|
462
|
+
|
|
463
|
+
def execute
|
|
464
|
+
encoding
|
|
465
|
+
end
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
> RecordInteraction.run!(encoding: Encoding::US_ASCII)
|
|
469
|
+
=> #<Encoding:US-ASCII>
|
|
470
|
+
|
|
471
|
+
> RecordInteraction.run!(encoding: 'ascii')
|
|
472
|
+
=> #<Encoding:US-ASCII>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
A different method can be specified by providing a symbol to the `finder` option.
|
|
476
|
+
|
|
421
477
|
### String
|
|
422
478
|
|
|
423
479
|
String filters define inputs that only accept strings.
|
|
@@ -1389,8 +1445,7 @@ I18nInteraction.run(name: false).errors.messages[:name]
|
|
|
1389
1445
|
## Credits
|
|
1390
1446
|
|
|
1391
1447
|
ActiveInteraction is brought to you by [Aaron Lasseigne][] and
|
|
1392
|
-
[Taylor Fausak][]
|
|
1393
|
-
by [Jonathan Novak][] on [Mutations][].
|
|
1448
|
+
[Taylor Fausak][] and was originally built at [OrgSync][].
|
|
1394
1449
|
|
|
1395
1450
|
If you want to contribute to ActiveInteraction, please read
|
|
1396
1451
|
[our contribution guidelines][]. A [complete list of contributors][] is
|
|
@@ -1408,8 +1463,6 @@ ActiveInteraction is licensed under [the MIT License][].
|
|
|
1408
1463
|
[aaron lasseigne]: https://github.com/AaronLasseigne
|
|
1409
1464
|
[taylor fausak]: https://github.com/tfausak
|
|
1410
1465
|
[orgsync]: https://github.com/orgsync
|
|
1411
|
-
[jonathan novak]: https://github.com/cypriss
|
|
1412
|
-
[mutations]: https://github.com/cypriss/mutations
|
|
1413
1466
|
[our contribution guidelines]: CONTRIBUTING.md
|
|
1414
1467
|
[complete list of contributors]: https://github.com/orgsync/active_interaction/graphs/contributors
|
|
1415
1468
|
[the mit license]: LICENSE.md
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'active_support/core_ext/hash/indifferent_access'
|
|
5
|
-
require 'set'
|
|
6
5
|
|
|
7
6
|
module ActiveInteraction
|
|
8
7
|
# @abstract Subclass and override {#execute} to implement a custom
|
|
@@ -233,17 +232,17 @@ module ActiveInteraction
|
|
|
233
232
|
# @return [Boolean]
|
|
234
233
|
#
|
|
235
234
|
# @since 2.1.0
|
|
236
|
-
def given?(input, *rest)
|
|
235
|
+
def given?(input, *rest) # rubocop:disable Metrics/CyclomaticComplexity
|
|
237
236
|
filter_level = self.class
|
|
238
237
|
input_level = @_interaction_inputs
|
|
239
238
|
|
|
240
239
|
[input, *rest].map(&:to_sym).each do |key|
|
|
241
240
|
filter_level = filter_level.filters[key]
|
|
242
|
-
if !filter_level || input_level.nil? || !input_level.key?(key)
|
|
243
|
-
break false
|
|
244
|
-
end
|
|
245
241
|
|
|
246
|
-
|
|
242
|
+
break false if filter_level.nil? || input_level.nil?
|
|
243
|
+
break false unless input_level.key?(key) || input_level.key?(key.to_s)
|
|
244
|
+
|
|
245
|
+
input_level = input_level[key] || input_level[key.to_s]
|
|
247
246
|
end && true
|
|
248
247
|
end
|
|
249
248
|
|
|
@@ -277,9 +276,7 @@ module ActiveInteraction
|
|
|
277
276
|
@_interaction_inputs = inputs
|
|
278
277
|
|
|
279
278
|
inputs.each do |key, value|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
populate_reader(key, value)
|
|
279
|
+
populate_reader(key, value) unless InputProcessor.reserved?(key)
|
|
283
280
|
end
|
|
284
281
|
|
|
285
282
|
populate_filters(InputProcessor.process(inputs))
|
|
@@ -13,6 +13,11 @@ module ActiveInteraction
|
|
|
13
13
|
# @return [Class]
|
|
14
14
|
InvalidClassError = Class.new(Error)
|
|
15
15
|
|
|
16
|
+
# Raised if a converter is invalid.
|
|
17
|
+
#
|
|
18
|
+
# @return [Class]
|
|
19
|
+
InvalidConverterError = Class.new(Error)
|
|
20
|
+
|
|
16
21
|
# Raised if a default value is invalid.
|
|
17
22
|
#
|
|
18
23
|
# @return [Class]
|
|
@@ -48,13 +53,6 @@ module ActiveInteraction
|
|
|
48
53
|
# @return [Class]
|
|
49
54
|
NoDefaultError = Class.new(Error)
|
|
50
55
|
|
|
51
|
-
# Raised if a reserved name is used.
|
|
52
|
-
#
|
|
53
|
-
# @return [Class]
|
|
54
|
-
#
|
|
55
|
-
# @since 1.2.0
|
|
56
|
-
ReservedNameError = Class.new(Error)
|
|
57
|
-
|
|
58
56
|
# Raised if a user-supplied value to a nested hash input is invalid.
|
|
59
57
|
#
|
|
60
58
|
# @return [Class]
|
|
@@ -133,7 +131,7 @@ module ActiveInteraction
|
|
|
133
131
|
end
|
|
134
132
|
|
|
135
133
|
def merge_detail!(other, attribute, detail, error)
|
|
136
|
-
if attribute?(attribute)
|
|
134
|
+
if attribute?(attribute) || attribute == :base
|
|
137
135
|
add(attribute, error, detail) unless added?(attribute, error, detail)
|
|
138
136
|
else
|
|
139
137
|
translated_error = translate(other, attribute, error)
|
|
@@ -10,6 +10,14 @@ module ActiveInteraction
|
|
|
10
10
|
# @!macro filter_method_params
|
|
11
11
|
# @option options [Class, String, Symbol] :class (use the attribute name)
|
|
12
12
|
# Class name used to ensure the value.
|
|
13
|
+
# @option options [Proc, Symbol] :converter A symbol specifying the name
|
|
14
|
+
# of a class method of `:class` or a Proc that is called when a new
|
|
15
|
+
# value is assigned to the value object. The converter is passed the
|
|
16
|
+
# single value that is used in the assignment and is only called if the
|
|
17
|
+
# new value is not an instance of `:class`. The class method or proc
|
|
18
|
+
# are passed the value. Any error thrown inside the converter is trapped
|
|
19
|
+
# and the value provided is treated as invalid. Any returned value that
|
|
20
|
+
# is not the correct class will also be treated as invalid.
|
|
13
21
|
#
|
|
14
22
|
# @example
|
|
15
23
|
# object :account
|
|
@@ -21,18 +29,29 @@ module ActiveInteraction
|
|
|
21
29
|
class ObjectFilter < Filter
|
|
22
30
|
register :object
|
|
23
31
|
|
|
24
|
-
|
|
32
|
+
# rubocop:disable Metrics/MethodLength
|
|
33
|
+
def cast(value, context, reconstantize: true, convert: true)
|
|
25
34
|
@klass ||= klass
|
|
26
35
|
|
|
27
36
|
if matches?(value)
|
|
28
37
|
value
|
|
29
|
-
|
|
30
|
-
return super(value, context) unless reconstantize
|
|
31
|
-
|
|
38
|
+
elsif reconstantize
|
|
32
39
|
@klass = klass
|
|
33
|
-
|
|
40
|
+
public_send(__method__, value, context,
|
|
41
|
+
reconstantize: false,
|
|
42
|
+
convert: convert
|
|
43
|
+
)
|
|
44
|
+
elsif !value.nil? && convert && (converter = options[:converter])
|
|
45
|
+
value = convert(klass, value, converter)
|
|
46
|
+
public_send(__method__, value, context,
|
|
47
|
+
reconstantize: reconstantize,
|
|
48
|
+
convert: false
|
|
49
|
+
)
|
|
50
|
+
else
|
|
51
|
+
super(value, context)
|
|
34
52
|
end
|
|
35
53
|
end
|
|
54
|
+
# rubocop:enable Metrics/MethodLength
|
|
36
55
|
|
|
37
56
|
private
|
|
38
57
|
|
|
@@ -53,5 +72,26 @@ module ActiveInteraction
|
|
|
53
72
|
@klass === value || # rubocop:disable Style/CaseEquality
|
|
54
73
|
value.is_a?(@klass)
|
|
55
74
|
end
|
|
75
|
+
|
|
76
|
+
def convert(klass, value, converter) # rubocop:disable Metrics/MethodLength
|
|
77
|
+
result =
|
|
78
|
+
case converter
|
|
79
|
+
when Proc
|
|
80
|
+
converter.call(value)
|
|
81
|
+
when Symbol
|
|
82
|
+
klass.public_send(converter, value)
|
|
83
|
+
else
|
|
84
|
+
raise InvalidConverterError,
|
|
85
|
+
"#{converter.inspect} is not a valid converter"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
raise InvalidValueError if result.nil?
|
|
89
|
+
|
|
90
|
+
result
|
|
91
|
+
rescue StandardError => e
|
|
92
|
+
raise e if e.is_a?(InvalidConverterError)
|
|
93
|
+
|
|
94
|
+
raise InvalidValueError
|
|
95
|
+
end
|
|
56
96
|
end
|
|
57
97
|
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveInteraction
|
|
4
|
+
class Base
|
|
5
|
+
# @!method self.record(*attributes, options = {})
|
|
6
|
+
# Creates accessors for the attributes and ensures that values passed to
|
|
7
|
+
# the attributes are the correct class.
|
|
8
|
+
#
|
|
9
|
+
# @!macro filter_method_params
|
|
10
|
+
# @option options [Class, String, Symbol] :class (use the attribute name)
|
|
11
|
+
# Class name used to ensure the value.
|
|
12
|
+
# @option options [Symbol] :finder A symbol specifying the name of a
|
|
13
|
+
# class method of `:class` that is called when a new value is assigned
|
|
14
|
+
# to the object. The finder is passed the single value that is used in
|
|
15
|
+
# the assignment and is only called if the new value is not an instance
|
|
16
|
+
# of `:class`. The class method is passed the value. Any error thrown
|
|
17
|
+
# inside the finder is trapped and the value provided is treated as
|
|
18
|
+
# invalid. Any returned value that is not the correct class will also
|
|
19
|
+
# be treated as invalid.
|
|
20
|
+
#
|
|
21
|
+
# @example
|
|
22
|
+
# record :account
|
|
23
|
+
# @example
|
|
24
|
+
# record :account, class: User
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# @private
|
|
28
|
+
class RecordFilter < Filter
|
|
29
|
+
register :record
|
|
30
|
+
|
|
31
|
+
# rubocop:disable Metrics/MethodLength
|
|
32
|
+
def cast(value, context, reconstantize: true, convert: true)
|
|
33
|
+
@klass ||= klass
|
|
34
|
+
|
|
35
|
+
if matches?(value)
|
|
36
|
+
value
|
|
37
|
+
elsif reconstantize
|
|
38
|
+
@klass = klass
|
|
39
|
+
public_send(__method__, value, context,
|
|
40
|
+
reconstantize: false,
|
|
41
|
+
convert: convert
|
|
42
|
+
)
|
|
43
|
+
elsif !value.nil? && convert
|
|
44
|
+
finder = options.fetch(:finder, :find)
|
|
45
|
+
value = find(klass, value, finder)
|
|
46
|
+
public_send(__method__, value, context,
|
|
47
|
+
reconstantize: reconstantize,
|
|
48
|
+
convert: false
|
|
49
|
+
)
|
|
50
|
+
else
|
|
51
|
+
super(value, context)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
# rubocop:enable Metrics/MethodLength
|
|
55
|
+
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
# @return [Class]
|
|
59
|
+
#
|
|
60
|
+
# @raise [InvalidClassError]
|
|
61
|
+
def klass
|
|
62
|
+
klass_name = options.fetch(:class, name).to_s.camelize
|
|
63
|
+
Object.const_get(klass_name)
|
|
64
|
+
rescue NameError
|
|
65
|
+
raise InvalidClassError, "class #{klass_name.inspect} does not exist"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @param value [Object]
|
|
69
|
+
#
|
|
70
|
+
# @return [Boolean]
|
|
71
|
+
def matches?(value)
|
|
72
|
+
@klass === value || # rubocop:disable Style/CaseEquality
|
|
73
|
+
value.is_a?(@klass)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def find(klass, value, finder)
|
|
77
|
+
result = klass.public_send(finder, value)
|
|
78
|
+
|
|
79
|
+
raise InvalidValueError if result.nil?
|
|
80
|
+
|
|
81
|
+
result
|
|
82
|
+
rescue StandardError => e
|
|
83
|
+
raise e if e.is_a?(InvalidConverterError)
|
|
84
|
+
|
|
85
|
+
raise InvalidValueError
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -14,13 +14,13 @@ module ActiveInteraction
|
|
|
14
14
|
|
|
15
15
|
def reserved?(name)
|
|
16
16
|
name.to_s.start_with?('_interaction_') ||
|
|
17
|
-
Base.
|
|
18
|
-
Base.
|
|
17
|
+
Base.method_defined?(name) ||
|
|
18
|
+
Base.private_method_defined?(name)
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def process(inputs)
|
|
22
22
|
inputs.stringify_keys.sort.each_with_object({}) do |(k, v), h|
|
|
23
|
-
|
|
23
|
+
next if reserved?(k)
|
|
24
24
|
|
|
25
25
|
if (match = GROUPED_INPUT_PATTERN.match(k))
|
|
26
26
|
assign_to_group!(h, *match.captures, v)
|
data/lib/active_interaction.rb
CHANGED
|
@@ -42,6 +42,7 @@ require 'active_interaction/filters/float_filter'
|
|
|
42
42
|
require 'active_interaction/filters/hash_filter'
|
|
43
43
|
require 'active_interaction/filters/integer_filter'
|
|
44
44
|
require 'active_interaction/filters/object_filter'
|
|
45
|
+
require 'active_interaction/filters/record_filter'
|
|
45
46
|
require 'active_interaction/filters/string_filter'
|
|
46
47
|
require 'active_interaction/filters/symbol_filter'
|
|
47
48
|
require 'active_interaction/filters/time_filter'
|
|
@@ -35,20 +35,11 @@ describe ActiveInteraction::Base do
|
|
|
35
35
|
subject(:interaction) { described_class.new(inputs) }
|
|
36
36
|
|
|
37
37
|
describe '.new(inputs = {})' do
|
|
38
|
-
it 'does not
|
|
39
|
-
key = :
|
|
38
|
+
it 'does not set instance vars for reserved input names' do
|
|
39
|
+
key = :execute
|
|
40
40
|
inputs[key] = nil
|
|
41
|
-
expect do
|
|
42
|
-
interaction
|
|
43
|
-
end.to raise_error ActiveInteraction::InvalidValueError
|
|
44
|
-
end
|
|
45
41
|
|
|
46
|
-
|
|
47
|
-
key = "_interaction_#{SecureRandom.hex}"
|
|
48
|
-
inputs[key] = nil
|
|
49
|
-
expect do
|
|
50
|
-
interaction
|
|
51
|
-
end.to raise_error ActiveInteraction::InvalidValueError
|
|
42
|
+
expect(interaction.instance_variable_defined?(:"@#{key}")).to be false
|
|
52
43
|
end
|
|
53
44
|
|
|
54
45
|
context 'with invalid inputs' do
|
|
@@ -449,7 +440,7 @@ describe ActiveInteraction::Base do
|
|
|
449
440
|
end
|
|
450
441
|
end
|
|
451
442
|
|
|
452
|
-
it 'is true when the nested
|
|
443
|
+
it 'is true when the nested inputs symbols are given' do
|
|
453
444
|
described_class.class_exec do
|
|
454
445
|
def execute
|
|
455
446
|
given?(:x, :y)
|
|
@@ -460,6 +451,17 @@ describe ActiveInteraction::Base do
|
|
|
460
451
|
expect(result).to be true
|
|
461
452
|
end
|
|
462
453
|
|
|
454
|
+
it 'is true when the nested inputs strings are given' do
|
|
455
|
+
described_class.class_exec do
|
|
456
|
+
def execute
|
|
457
|
+
given?(:x, :y)
|
|
458
|
+
end
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
inputs['x'] = { 'y' => false }
|
|
462
|
+
expect(result).to be true
|
|
463
|
+
end
|
|
464
|
+
|
|
463
465
|
it 'is false when the nested input is not given' do
|
|
464
466
|
described_class.class_exec do
|
|
465
467
|
def execute
|
|
@@ -68,6 +68,17 @@ describe ActiveInteraction::Errors do
|
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
+
context 'that is a symbol on base' do
|
|
72
|
+
before do
|
|
73
|
+
other.add(:base)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'adds the error' do
|
|
77
|
+
errors.merge!(other)
|
|
78
|
+
expect(errors.details[:base]).to eql [{ error: :invalid }]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
71
82
|
context 'that is a string' do
|
|
72
83
|
let(:message) { SecureRandom.hex }
|
|
73
84
|
|
|
@@ -97,7 +108,8 @@ describe ActiveInteraction::Errors do
|
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
110
|
}
|
|
100
|
-
}
|
|
111
|
+
}
|
|
112
|
+
)
|
|
101
113
|
|
|
102
114
|
other.add(:attribute, :invalid_type, type: nil)
|
|
103
115
|
end
|
|
@@ -2,19 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
|
|
5
|
-
class
|
|
6
|
-
|
|
5
|
+
class ObjectThing
|
|
6
|
+
def self.converter(_)
|
|
7
|
+
@converter ||= new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.converter_with_error(_)
|
|
11
|
+
raise 'error'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
class ObjectThings; end
|
|
15
|
+
BackupObjectThing = ObjectThing
|
|
7
16
|
|
|
8
17
|
describe ActiveInteraction::ObjectFilter, :filter do
|
|
9
18
|
include_context 'filters'
|
|
10
19
|
it_behaves_like 'a filter'
|
|
11
20
|
|
|
12
21
|
before do
|
|
13
|
-
options[:class] =
|
|
22
|
+
options[:class] = ObjectThing
|
|
14
23
|
end
|
|
15
24
|
|
|
16
25
|
describe '#cast' do
|
|
17
|
-
let(:value) {
|
|
26
|
+
let(:value) { ObjectThing.new }
|
|
18
27
|
let(:result) { filter.cast(value, nil) }
|
|
19
28
|
|
|
20
29
|
context 'with class as a Class' do
|
|
@@ -25,9 +34,9 @@ describe ActiveInteraction::ObjectFilter, :filter do
|
|
|
25
34
|
it 'handles reconstantizing' do
|
|
26
35
|
expect(result).to eql value
|
|
27
36
|
|
|
28
|
-
Object.send(:remove_const, :
|
|
29
|
-
|
|
30
|
-
value =
|
|
37
|
+
Object.send(:remove_const, :ObjectThing)
|
|
38
|
+
ObjectThing = BackupObjectThing
|
|
39
|
+
value = ObjectThing.new
|
|
31
40
|
|
|
32
41
|
expect(filter.cast(value, nil)).to eql value
|
|
33
42
|
end
|
|
@@ -35,29 +44,17 @@ describe ActiveInteraction::ObjectFilter, :filter do
|
|
|
35
44
|
it 'handles reconstantizing subclasses' do
|
|
36
45
|
filter
|
|
37
46
|
|
|
38
|
-
Object.send(:remove_const, :
|
|
39
|
-
|
|
40
|
-
class
|
|
41
|
-
value =
|
|
47
|
+
Object.send(:remove_const, :ObjectThing)
|
|
48
|
+
ObjectThing = BackupObjectThing
|
|
49
|
+
class SubObjectThing < ObjectThing; end
|
|
50
|
+
value = SubObjectThing.new
|
|
42
51
|
|
|
43
52
|
expect(filter.cast(value, nil)).to eql value
|
|
44
53
|
end
|
|
45
54
|
|
|
46
|
-
it 'does not overflow the stack' do
|
|
47
|
-
klass = Class.new do
|
|
48
|
-
def self.name
|
|
49
|
-
Thing.name
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
expect do
|
|
54
|
-
filter.cast(klass.new, nil)
|
|
55
|
-
end.to raise_error ActiveInteraction::InvalidValueError
|
|
56
|
-
end
|
|
57
|
-
|
|
58
55
|
context 'without the class available' do
|
|
59
|
-
before { Object.send(:remove_const, :
|
|
60
|
-
after {
|
|
56
|
+
before { Object.send(:remove_const, :ObjectThing) }
|
|
57
|
+
after { ObjectThing = BackupObjectThing }
|
|
61
58
|
|
|
62
59
|
it 'does not raise an error on initialization' do
|
|
63
60
|
expect { filter }.to_not raise_error
|
|
@@ -69,7 +66,7 @@ describe ActiveInteraction::ObjectFilter, :filter do
|
|
|
69
66
|
let(:class_equality) { false }
|
|
70
67
|
|
|
71
68
|
before do
|
|
72
|
-
allow(
|
|
69
|
+
allow(ObjectThing).to receive(:===).and_return(case_equality)
|
|
73
70
|
allow(value).to receive(:is_a?).and_return(class_equality)
|
|
74
71
|
end
|
|
75
72
|
|
|
@@ -101,7 +98,7 @@ describe ActiveInteraction::ObjectFilter, :filter do
|
|
|
101
98
|
|
|
102
99
|
context 'with class as a superclass' do
|
|
103
100
|
before do
|
|
104
|
-
options[:class] =
|
|
101
|
+
options[:class] = ObjectThing.superclass
|
|
105
102
|
end
|
|
106
103
|
|
|
107
104
|
it 'returns the instance' do
|
|
@@ -111,7 +108,7 @@ describe ActiveInteraction::ObjectFilter, :filter do
|
|
|
111
108
|
|
|
112
109
|
context 'with class as a String' do
|
|
113
110
|
before do
|
|
114
|
-
options[:class] =
|
|
111
|
+
options[:class] = ObjectThing.name
|
|
115
112
|
end
|
|
116
113
|
|
|
117
114
|
it 'returns the instance' do
|
|
@@ -120,9 +117,9 @@ describe ActiveInteraction::ObjectFilter, :filter do
|
|
|
120
117
|
end
|
|
121
118
|
|
|
122
119
|
context 'with a plural class' do
|
|
123
|
-
let(:value) {
|
|
120
|
+
let(:value) { ObjectThings.new }
|
|
124
121
|
|
|
125
|
-
before { options[:class] =
|
|
122
|
+
before { options[:class] = ObjectThings }
|
|
126
123
|
|
|
127
124
|
it 'returns the instance' do
|
|
128
125
|
expect(result).to eql value
|
|
@@ -140,6 +137,116 @@ describe ActiveInteraction::ObjectFilter, :filter do
|
|
|
140
137
|
end.to raise_error ActiveInteraction::InvalidClassError
|
|
141
138
|
end
|
|
142
139
|
end
|
|
140
|
+
|
|
141
|
+
context 'with a converter' do
|
|
142
|
+
let(:value) { '' }
|
|
143
|
+
|
|
144
|
+
context 'that is a symbol' do
|
|
145
|
+
before do
|
|
146
|
+
options[:converter] = :converter
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'calls the class method' do
|
|
150
|
+
expect(result).to eql ObjectThing.converter(value)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
context 'that is a proc' do
|
|
155
|
+
before do
|
|
156
|
+
options[:converter] = ->(x) { ObjectThing.converter(x) }
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'gets called' do
|
|
160
|
+
expect(result).to eql ObjectThing.converter(value)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context 'with a object of the correct class' do
|
|
165
|
+
let(:value) { ObjectThing.new }
|
|
166
|
+
|
|
167
|
+
it 'does not call the converter' do
|
|
168
|
+
expect(ObjectThing).to_not receive(:converter)
|
|
169
|
+
expect(result).to eql value
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
context 'with a object is a subclass' do
|
|
174
|
+
let(:subclass) { Class.new(ObjectThing) }
|
|
175
|
+
let(:value) { subclass.new }
|
|
176
|
+
|
|
177
|
+
it 'does not call the converter' do
|
|
178
|
+
expect(subclass).to_not receive(:converter)
|
|
179
|
+
expect(result).to eql value
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
context 'with a nil value' do
|
|
184
|
+
let(:value) { nil }
|
|
185
|
+
include_context 'optional'
|
|
186
|
+
|
|
187
|
+
it 'returns nil' do
|
|
188
|
+
expect(ObjectThing).to_not receive(:converter)
|
|
189
|
+
expect(result).to eql value
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context 'that is invalid' do
|
|
194
|
+
before do
|
|
195
|
+
options[:converter] = 'invalid converter'
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it 'raises an error' do
|
|
199
|
+
expect do
|
|
200
|
+
result
|
|
201
|
+
end.to raise_error ActiveInteraction::InvalidConverterError
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
context 'that throws an error' do
|
|
206
|
+
before do
|
|
207
|
+
options[:converter] = :converter_with_error
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it 'raises an error' do
|
|
211
|
+
expect do
|
|
212
|
+
result
|
|
213
|
+
end.to raise_error ActiveInteraction::InvalidValueError
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
describe '#clean' do
|
|
220
|
+
context 'with a converter' do
|
|
221
|
+
context 'that returns a nil' do
|
|
222
|
+
let(:value) { '' }
|
|
223
|
+
|
|
224
|
+
before do
|
|
225
|
+
options[:default] = ObjectThing.new
|
|
226
|
+
options[:converter] = ->(_) { nil }
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it 'raises an error' do
|
|
230
|
+
expect do
|
|
231
|
+
filter.clean(value, nil)
|
|
232
|
+
end.to raise_error ActiveInteraction::InvalidValueError
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
context 'that returns an invalid value' do
|
|
237
|
+
let(:value) { '' }
|
|
238
|
+
|
|
239
|
+
before do
|
|
240
|
+
options[:converter] = ->(_) { 'invalid' }
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
it 'raises an error' do
|
|
244
|
+
expect do
|
|
245
|
+
filter.clean(value, nil)
|
|
246
|
+
end.to raise_error ActiveInteraction::InvalidValueError
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
143
250
|
end
|
|
144
251
|
|
|
145
252
|
describe '#database_column_type' do
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
class RecordThing
|
|
4
|
+
def self.find(_)
|
|
5
|
+
raise 'error'
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.finder(_)
|
|
9
|
+
@record2 ||= new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.finds_nil(_)
|
|
13
|
+
nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.finds_bad_value(_)
|
|
17
|
+
''
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.passthrough(x)
|
|
21
|
+
x
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
class RecordThings; end
|
|
25
|
+
BackupRecordThing = RecordThing
|
|
26
|
+
|
|
27
|
+
describe ActiveInteraction::RecordFilter, :filter do
|
|
28
|
+
include_context 'filters'
|
|
29
|
+
it_behaves_like 'a filter'
|
|
30
|
+
|
|
31
|
+
before do
|
|
32
|
+
options[:class] = RecordThing
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe '#cast' do
|
|
36
|
+
before do
|
|
37
|
+
options[:finder] = :finder
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
let(:value) { RecordThing.new }
|
|
41
|
+
let(:result) { filter.cast(value, nil) }
|
|
42
|
+
|
|
43
|
+
context 'with class as a Class' do
|
|
44
|
+
it 'returns the instance' do
|
|
45
|
+
expect(result).to eql value
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'handles reconstantizing' do
|
|
49
|
+
expect(result).to eql value
|
|
50
|
+
|
|
51
|
+
Object.send(:remove_const, :RecordThing)
|
|
52
|
+
RecordThing = BackupRecordThing
|
|
53
|
+
value = RecordThing.new
|
|
54
|
+
|
|
55
|
+
expect(filter.cast(value, nil)).to eql value
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'handles reconstantizing subclasses' do
|
|
59
|
+
filter
|
|
60
|
+
|
|
61
|
+
Object.send(:remove_const, :RecordThing)
|
|
62
|
+
RecordThing = BackupRecordThing
|
|
63
|
+
class SubRecordThing < RecordThing; end
|
|
64
|
+
value = SubRecordThing.new
|
|
65
|
+
|
|
66
|
+
expect(filter.cast(value, nil)).to eql value
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'without the class available' do
|
|
70
|
+
before { Object.send(:remove_const, :RecordThing) }
|
|
71
|
+
after { RecordThing = BackupRecordThing }
|
|
72
|
+
|
|
73
|
+
it 'does not raise an error on initialization' do
|
|
74
|
+
expect { filter }.to_not raise_error
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
context 'with bidirectional class comparisons' do
|
|
79
|
+
let(:case_equality) { false }
|
|
80
|
+
let(:class_equality) { false }
|
|
81
|
+
|
|
82
|
+
before do
|
|
83
|
+
options[:finder] = :passthrough
|
|
84
|
+
|
|
85
|
+
allow(RecordThing).to receive(:===).and_return(case_equality)
|
|
86
|
+
allow(value).to receive(:is_a?).and_return(class_equality)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
context 'without case or class equality' do
|
|
90
|
+
it 'raises an error' do
|
|
91
|
+
expect do
|
|
92
|
+
result
|
|
93
|
+
end.to raise_error ActiveInteraction::InvalidValueError
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context 'with case equality' do
|
|
98
|
+
let(:case_equality) { true }
|
|
99
|
+
|
|
100
|
+
it 'returns the instance' do
|
|
101
|
+
expect(result).to eql value
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
context 'with class equality' do
|
|
106
|
+
let(:class_equality) { true }
|
|
107
|
+
|
|
108
|
+
it 'returns the instance' do
|
|
109
|
+
expect(result).to eql value
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context 'with class as a superclass' do
|
|
116
|
+
before do
|
|
117
|
+
options[:class] = RecordThing.superclass
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'returns the instance' do
|
|
121
|
+
expect(result).to eql value
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context 'with class as a String' do
|
|
126
|
+
before do
|
|
127
|
+
options[:class] = RecordThing.name
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'returns the instance' do
|
|
131
|
+
expect(result).to eql value
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
context 'with a plural class' do
|
|
136
|
+
let(:value) { RecordThings.new }
|
|
137
|
+
|
|
138
|
+
before { options[:class] = RecordThings }
|
|
139
|
+
|
|
140
|
+
it 'returns the instance' do
|
|
141
|
+
expect(result).to eql value
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
context 'with class as an invalid String' do
|
|
146
|
+
before do
|
|
147
|
+
options[:class] = 'invalid'
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it 'raises an error' do
|
|
151
|
+
expect do
|
|
152
|
+
result
|
|
153
|
+
end.to raise_error ActiveInteraction::InvalidClassError
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context 'with a value that does not match the class' do
|
|
158
|
+
let(:value) { '' }
|
|
159
|
+
|
|
160
|
+
it 'calls the finder' do
|
|
161
|
+
expect(result).to eql RecordThing.finder(value)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context 'with a custom finder' do
|
|
165
|
+
it 'calls the custom finder' do
|
|
166
|
+
expect(result).to eql RecordThing.finder(value)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe '#clean' do
|
|
173
|
+
context 'with a value that does not match the class' do
|
|
174
|
+
context 'that returns a nil' do
|
|
175
|
+
let(:value) { '' }
|
|
176
|
+
|
|
177
|
+
before do
|
|
178
|
+
options[:default] = RecordThing.new
|
|
179
|
+
options[:finder] = :finds_nil
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'raises an error' do
|
|
183
|
+
expect do
|
|
184
|
+
filter.clean(value, nil)
|
|
185
|
+
end.to raise_error ActiveInteraction::InvalidValueError
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
context 'that returns an invalid value' do
|
|
190
|
+
let(:value) { '' }
|
|
191
|
+
|
|
192
|
+
before do
|
|
193
|
+
options[:finder] = :finds_bad_value
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'raises an error' do
|
|
197
|
+
expect do
|
|
198
|
+
filter.clean(value, nil)
|
|
199
|
+
end.to raise_error ActiveInteraction::InvalidValueError
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
describe '#database_column_type' do
|
|
206
|
+
it 'returns :string' do
|
|
207
|
+
expect(filter.database_column_type).to eql :string
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
end
|
|
@@ -74,10 +74,8 @@ describe ActiveInteraction::InputProcessor do
|
|
|
74
74
|
context 'with a reserved name' do
|
|
75
75
|
before { inputs[:_interaction_key] = :value }
|
|
76
76
|
|
|
77
|
-
it '
|
|
78
|
-
expect
|
|
79
|
-
result
|
|
80
|
-
end.to raise_error ActiveInteraction::ReservedNameError
|
|
77
|
+
it 'skips the input' do
|
|
78
|
+
expect(result).to_not have_key(:_interaction_key)
|
|
81
79
|
end
|
|
82
80
|
end
|
|
83
81
|
end
|
|
@@ -24,11 +24,14 @@ shared_examples_for 'an interaction' do |type, generator, filter_options = {}|
|
|
|
24
24
|
public_send(type, :required, filter_options)
|
|
25
25
|
public_send(type, :optional, filter_options.merge(default: nil))
|
|
26
26
|
public_send(type, :default,
|
|
27
|
-
filter_options.merge(default: generator.call)
|
|
27
|
+
filter_options.merge(default: generator.call)
|
|
28
|
+
)
|
|
28
29
|
public_send(type, :defaults_1, :defaults_2,
|
|
29
|
-
filter_options.merge(default: generator.call)
|
|
30
|
+
filter_options.merge(default: generator.call)
|
|
31
|
+
)
|
|
30
32
|
public_send(type, :defaults_3,
|
|
31
|
-
filter_options.merge(default: -> { required })
|
|
33
|
+
filter_options.merge(default: -> { required })
|
|
34
|
+
)
|
|
32
35
|
end
|
|
33
36
|
end
|
|
34
37
|
|
|
@@ -36,7 +39,8 @@ shared_examples_for 'an interaction' do |type, generator, filter_options = {}|
|
|
|
36
39
|
let(:described_class) do
|
|
37
40
|
Class.new(TestInteraction) do
|
|
38
41
|
public_send(type, :default,
|
|
39
|
-
filter_options.merge(default: -> { Object.new })
|
|
42
|
+
filter_options.merge(default: -> { Object.new })
|
|
43
|
+
)
|
|
40
44
|
end
|
|
41
45
|
end
|
|
42
46
|
|
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: 3.
|
|
4
|
+
version: 3.6.0
|
|
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: 2017-
|
|
12
|
+
date: 2017-10-20 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activemodel
|
|
@@ -196,6 +196,7 @@ files:
|
|
|
196
196
|
- lib/active_interaction/filters/integer_filter.rb
|
|
197
197
|
- lib/active_interaction/filters/interface_filter.rb
|
|
198
198
|
- lib/active_interaction/filters/object_filter.rb
|
|
199
|
+
- lib/active_interaction/filters/record_filter.rb
|
|
199
200
|
- lib/active_interaction/filters/string_filter.rb
|
|
200
201
|
- lib/active_interaction/filters/symbol_filter.rb
|
|
201
202
|
- lib/active_interaction/filters/time_filter.rb
|
|
@@ -229,6 +230,7 @@ files:
|
|
|
229
230
|
- spec/active_interaction/filters/integer_filter_spec.rb
|
|
230
231
|
- spec/active_interaction/filters/interface_filter_spec.rb
|
|
231
232
|
- spec/active_interaction/filters/object_filter_spec.rb
|
|
233
|
+
- spec/active_interaction/filters/record_filter_spec.rb
|
|
232
234
|
- spec/active_interaction/filters/string_filter_spec.rb
|
|
233
235
|
- spec/active_interaction/filters/symbol_filter_spec.rb
|
|
234
236
|
- spec/active_interaction/filters/time_filter_spec.rb
|
|
@@ -253,7 +255,7 @@ files:
|
|
|
253
255
|
- spec/support/concerns.rb
|
|
254
256
|
- spec/support/filters.rb
|
|
255
257
|
- spec/support/interactions.rb
|
|
256
|
-
homepage:
|
|
258
|
+
homepage: https://github.com/AaronLasseigne/active_interaction
|
|
257
259
|
licenses:
|
|
258
260
|
- MIT
|
|
259
261
|
metadata: {}
|
|
@@ -273,55 +275,56 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
273
275
|
version: '0'
|
|
274
276
|
requirements: []
|
|
275
277
|
rubyforge_project:
|
|
276
|
-
rubygems_version: 2.6.
|
|
278
|
+
rubygems_version: 2.6.13
|
|
277
279
|
signing_key:
|
|
278
280
|
specification_version: 4
|
|
279
281
|
summary: Manage application specific business logic.
|
|
280
282
|
test_files:
|
|
281
|
-
- spec/
|
|
282
|
-
- spec/active_interaction/
|
|
283
|
-
- spec/active_interaction/
|
|
284
|
-
- spec/active_interaction/concerns/hashable_spec.rb
|
|
285
|
-
- spec/active_interaction/concerns/missable_spec.rb
|
|
286
|
-
- spec/active_interaction/concerns/runnable_spec.rb
|
|
287
|
-
- spec/active_interaction/errors_spec.rb
|
|
288
|
-
- spec/active_interaction/filter_column_spec.rb
|
|
289
|
-
- spec/active_interaction/filter_spec.rb
|
|
283
|
+
- spec/spec_helper.rb
|
|
284
|
+
- spec/active_interaction/grouped_input_spec.rb
|
|
285
|
+
- spec/active_interaction/filters/hash_filter_spec.rb
|
|
290
286
|
- spec/active_interaction/filters/abstract_date_time_filter_spec.rb
|
|
291
|
-
- spec/active_interaction/filters/abstract_filter_spec.rb
|
|
292
|
-
- spec/active_interaction/filters/abstract_numeric_filter_spec.rb
|
|
293
|
-
- spec/active_interaction/filters/array_filter_spec.rb
|
|
294
287
|
- spec/active_interaction/filters/boolean_filter_spec.rb
|
|
295
|
-
- spec/active_interaction/filters/
|
|
296
|
-
- spec/active_interaction/filters/
|
|
297
|
-
- spec/active_interaction/filters/
|
|
298
|
-
- spec/active_interaction/filters/file_filter_spec.rb
|
|
288
|
+
- spec/active_interaction/filters/array_filter_spec.rb
|
|
289
|
+
- spec/active_interaction/filters/time_filter_spec.rb
|
|
290
|
+
- spec/active_interaction/filters/abstract_filter_spec.rb
|
|
299
291
|
- spec/active_interaction/filters/float_filter_spec.rb
|
|
300
|
-
- spec/active_interaction/filters/
|
|
292
|
+
- spec/active_interaction/filters/date_filter_spec.rb
|
|
301
293
|
- spec/active_interaction/filters/integer_filter_spec.rb
|
|
302
|
-
- spec/active_interaction/filters/interface_filter_spec.rb
|
|
303
294
|
- spec/active_interaction/filters/object_filter_spec.rb
|
|
304
|
-
- spec/active_interaction/filters/string_filter_spec.rb
|
|
305
295
|
- spec/active_interaction/filters/symbol_filter_spec.rb
|
|
306
|
-
- spec/active_interaction/filters/
|
|
307
|
-
- spec/active_interaction/
|
|
296
|
+
- spec/active_interaction/filters/string_filter_spec.rb
|
|
297
|
+
- spec/active_interaction/filters/abstract_numeric_filter_spec.rb
|
|
298
|
+
- spec/active_interaction/filters/decimal_filter_spec.rb
|
|
299
|
+
- spec/active_interaction/filters/file_filter_spec.rb
|
|
300
|
+
- spec/active_interaction/filters/interface_filter_spec.rb
|
|
301
|
+
- spec/active_interaction/filters/record_filter_spec.rb
|
|
302
|
+
- spec/active_interaction/filters/date_time_filter_spec.rb
|
|
308
303
|
- spec/active_interaction/i18n_spec.rb
|
|
309
|
-
- spec/active_interaction/integration/array_interaction_spec.rb
|
|
310
304
|
- spec/active_interaction/integration/boolean_interaction_spec.rb
|
|
311
305
|
- spec/active_interaction/integration/date_interaction_spec.rb
|
|
312
|
-
- spec/active_interaction/integration/
|
|
313
|
-
- spec/active_interaction/integration/
|
|
306
|
+
- spec/active_interaction/integration/symbol_interaction_spec.rb
|
|
307
|
+
- spec/active_interaction/integration/interface_interaction_spec.rb
|
|
308
|
+
- spec/active_interaction/integration/time_interaction_spec.rb
|
|
314
309
|
- spec/active_interaction/integration/float_interaction_spec.rb
|
|
315
|
-
- spec/active_interaction/integration/hash_interaction_spec.rb
|
|
316
310
|
- spec/active_interaction/integration/integer_interaction_spec.rb
|
|
317
|
-
- spec/active_interaction/integration/interface_interaction_spec.rb
|
|
318
|
-
- spec/active_interaction/integration/object_interaction_spec.rb
|
|
319
311
|
- spec/active_interaction/integration/string_interaction_spec.rb
|
|
320
|
-
- spec/active_interaction/integration/
|
|
321
|
-
- spec/active_interaction/integration/
|
|
322
|
-
- spec/active_interaction/
|
|
312
|
+
- spec/active_interaction/integration/array_interaction_spec.rb
|
|
313
|
+
- spec/active_interaction/integration/hash_interaction_spec.rb
|
|
314
|
+
- spec/active_interaction/integration/date_time_interaction_spec.rb
|
|
315
|
+
- spec/active_interaction/integration/file_interaction_spec.rb
|
|
316
|
+
- spec/active_interaction/integration/object_interaction_spec.rb
|
|
317
|
+
- spec/active_interaction/filter_column_spec.rb
|
|
318
|
+
- spec/active_interaction/errors_spec.rb
|
|
323
319
|
- spec/active_interaction/modules/validation_spec.rb
|
|
324
|
-
- spec/
|
|
325
|
-
- spec/
|
|
320
|
+
- spec/active_interaction/modules/input_processor_spec.rb
|
|
321
|
+
- spec/active_interaction/filter_spec.rb
|
|
322
|
+
- spec/active_interaction/base_spec.rb
|
|
323
|
+
- spec/active_interaction/concerns/active_modelable_spec.rb
|
|
324
|
+
- spec/active_interaction/concerns/hashable_spec.rb
|
|
325
|
+
- spec/active_interaction/concerns/active_recordable_spec.rb
|
|
326
|
+
- spec/active_interaction/concerns/missable_spec.rb
|
|
327
|
+
- spec/active_interaction/concerns/runnable_spec.rb
|
|
326
328
|
- spec/support/filters.rb
|
|
327
329
|
- spec/support/interactions.rb
|
|
330
|
+
- spec/support/concerns.rb
|