active_interaction 3.7.1 → 4.0.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/CHANGELOG.md +190 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +96 -90
- data/lib/active_interaction.rb +1 -7
- data/lib/active_interaction/base.rb +48 -33
- data/lib/active_interaction/concerns/active_modelable.rb +1 -3
- data/lib/active_interaction/concerns/active_recordable.rb +1 -6
- data/lib/active_interaction/concerns/hashable.rb +0 -1
- data/lib/active_interaction/concerns/missable.rb +0 -1
- data/lib/active_interaction/concerns/runnable.rb +16 -28
- data/lib/active_interaction/errors.rb +8 -7
- data/lib/active_interaction/filter.rb +51 -37
- data/lib/active_interaction/filter_column.rb +0 -3
- data/lib/active_interaction/filters/abstract_date_time_filter.rb +34 -36
- data/lib/active_interaction/filters/abstract_numeric_filter.rb +27 -17
- data/lib/active_interaction/filters/array_filter.rb +57 -36
- data/lib/active_interaction/filters/boolean_filter.rb +26 -12
- data/lib/active_interaction/filters/date_filter.rb +1 -2
- data/lib/active_interaction/filters/date_time_filter.rb +1 -2
- data/lib/active_interaction/filters/decimal_filter.rb +10 -28
- data/lib/active_interaction/filters/file_filter.rb +6 -5
- data/lib/active_interaction/filters/float_filter.rb +1 -2
- data/lib/active_interaction/filters/hash_filter.rb +37 -27
- data/lib/active_interaction/filters/integer_filter.rb +7 -8
- data/lib/active_interaction/filters/interface_filter.rb +48 -14
- data/lib/active_interaction/filters/object_filter.rb +23 -50
- data/lib/active_interaction/filters/record_filter.rb +10 -35
- data/lib/active_interaction/filters/string_filter.rb +21 -12
- data/lib/active_interaction/filters/symbol_filter.rb +13 -7
- data/lib/active_interaction/filters/time_filter.rb +19 -22
- data/lib/active_interaction/grouped_input.rb +0 -3
- data/lib/active_interaction/inputs.rb +89 -0
- data/lib/active_interaction/locale/ja.yml +24 -0
- data/lib/active_interaction/modules/input_processor.rb +9 -6
- data/lib/active_interaction/modules/validation.rb +9 -12
- data/lib/active_interaction/version.rb +1 -3
- data/spec/active_interaction/base_spec.rb +95 -35
- data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -2
- data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -2
- data/spec/active_interaction/concerns/hashable_spec.rb +1 -3
- data/spec/active_interaction/concerns/missable_spec.rb +0 -2
- data/spec/active_interaction/concerns/runnable_spec.rb +32 -12
- data/spec/active_interaction/errors_spec.rb +49 -22
- data/spec/active_interaction/filter_column_spec.rb +0 -2
- data/spec/active_interaction/filter_spec.rb +0 -2
- data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +1 -3
- data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +1 -3
- data/spec/active_interaction/filters/array_filter_spec.rb +41 -15
- data/spec/active_interaction/filters/boolean_filter_spec.rb +58 -4
- data/spec/active_interaction/filters/date_filter_spec.rb +43 -3
- data/spec/active_interaction/filters/date_time_filter_spec.rb +43 -3
- data/spec/active_interaction/filters/decimal_filter_spec.rb +57 -3
- data/spec/active_interaction/filters/file_filter_spec.rb +1 -3
- data/spec/active_interaction/filters/float_filter_spec.rb +60 -4
- data/spec/active_interaction/filters/hash_filter_spec.rb +19 -9
- data/spec/active_interaction/filters/integer_filter_spec.rb +49 -7
- data/spec/active_interaction/filters/interface_filter_spec.rb +397 -24
- data/spec/active_interaction/filters/object_filter_spec.rb +23 -59
- data/spec/active_interaction/filters/record_filter_spec.rb +23 -49
- data/spec/active_interaction/filters/string_filter_spec.rb +15 -3
- data/spec/active_interaction/filters/symbol_filter_spec.rb +15 -3
- data/spec/active_interaction/filters/time_filter_spec.rb +65 -3
- data/spec/active_interaction/grouped_input_spec.rb +0 -2
- data/spec/active_interaction/i18n_spec.rb +3 -7
- data/spec/active_interaction/{modules/input_processor_spec.rb → inputs_spec.rb} +5 -5
- data/spec/active_interaction/integration/array_interaction_spec.rb +23 -12
- data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/date_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/file_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/float_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/interface_interaction_spec.rb +1 -3
- data/spec/active_interaction/integration/object_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/string_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -2
- data/spec/active_interaction/integration/time_interaction_spec.rb +14 -18
- data/spec/active_interaction/modules/validation_spec.rb +1 -3
- data/spec/spec_helper.rb +2 -6
- data/spec/support/concerns.rb +0 -2
- data/spec/support/filters.rb +13 -9
- data/spec/support/interactions.rb +22 -14
- metadata +106 -52
- data/lib/active_interaction/backports.rb +0 -59
- data/lib/active_interaction/filters/abstract_filter.rb +0 -19
- data/spec/active_interaction/filters/abstract_filter_spec.rb +0 -8
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module ActiveInteraction
|
|
5
|
-
class Base
|
|
4
|
+
class Base # rubocop:disable Lint/EmptyClass
|
|
6
5
|
# @!method self.symbol(*attributes, options = {})
|
|
7
6
|
# Creates accessors for the attributes and ensures that values passed to
|
|
8
7
|
# the attributes are Symbols. Strings will be converted to Symbols.
|
|
@@ -17,15 +16,22 @@ module ActiveInteraction
|
|
|
17
16
|
class SymbolFilter < Filter
|
|
18
17
|
register :symbol
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def matches?(value)
|
|
22
|
+
value.is_a?(Symbol)
|
|
23
|
+
rescue NoMethodError # BasicObject
|
|
24
|
+
false
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def convert(value)
|
|
28
|
+
if value.respond_to?(:to_sym)
|
|
25
29
|
value.to_sym
|
|
26
30
|
else
|
|
27
31
|
super
|
|
28
32
|
end
|
|
33
|
+
rescue NoMethodError # BasicObject
|
|
34
|
+
super
|
|
29
35
|
end
|
|
30
36
|
end
|
|
31
37
|
end
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module ActiveInteraction
|
|
5
|
-
class Base
|
|
4
|
+
class Base # rubocop:disable Lint/EmptyClass
|
|
6
5
|
# @!method self.time(*attributes, options = {})
|
|
7
6
|
# Creates accessors for the attributes and ensures that values passed to
|
|
8
7
|
# the attributes are Times. Numeric values are processed using `at`.
|
|
@@ -24,42 +23,40 @@ module ActiveInteraction
|
|
|
24
23
|
class TimeFilter < AbstractDateTimeFilter
|
|
25
24
|
register :time
|
|
26
25
|
|
|
27
|
-
alias _klass klass
|
|
28
|
-
private :_klass
|
|
29
|
-
|
|
30
26
|
def initialize(name, options = {}, &block)
|
|
31
|
-
if options.key?(:format) &&
|
|
32
|
-
raise InvalidFilterError, 'format option unsupported with time zones'
|
|
33
|
-
end
|
|
27
|
+
raise InvalidFilterError, 'format option unsupported with time zones' if options.key?(:format) && time_with_zone?
|
|
34
28
|
|
|
35
29
|
super
|
|
36
30
|
end
|
|
37
31
|
|
|
38
|
-
def cast(value, _interaction)
|
|
39
|
-
case value
|
|
40
|
-
when Numeric
|
|
41
|
-
klass.at(value)
|
|
42
|
-
else
|
|
43
|
-
super
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
32
|
def database_column_type
|
|
48
33
|
:datetime
|
|
49
34
|
end
|
|
50
35
|
|
|
51
36
|
private
|
|
52
37
|
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
|
|
38
|
+
def time_with_zone?
|
|
39
|
+
Time.respond_to?(:zone) && !Time.zone.nil?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def klasses
|
|
43
|
+
if time_with_zone?
|
|
44
|
+
super + [Time.zone.class]
|
|
56
45
|
else
|
|
57
46
|
super
|
|
58
47
|
end
|
|
59
48
|
end
|
|
60
49
|
|
|
61
|
-
def
|
|
62
|
-
|
|
50
|
+
def convert(value)
|
|
51
|
+
value = value.to_int if value.respond_to?(:to_int)
|
|
52
|
+
|
|
53
|
+
if value.is_a?(Numeric)
|
|
54
|
+
klass.at(value)
|
|
55
|
+
else
|
|
56
|
+
super
|
|
57
|
+
end
|
|
58
|
+
rescue NoMethodError # BasicObject
|
|
59
|
+
super
|
|
63
60
|
end
|
|
64
61
|
end
|
|
65
62
|
end
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
require 'ostruct'
|
|
@@ -6,8 +5,6 @@ require 'ostruct'
|
|
|
6
5
|
module ActiveInteraction
|
|
7
6
|
# Holds a group of inputs together for passing from {Base} to {Filter}s.
|
|
8
7
|
#
|
|
9
|
-
# @since 1.2.0
|
|
10
|
-
#
|
|
11
8
|
# @private
|
|
12
9
|
class GroupedInput < OpenStruct
|
|
13
10
|
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveInteraction
|
|
4
|
+
# Holds inputs passed to the interaction.
|
|
5
|
+
class Inputs < DelegateClass(Hash)
|
|
6
|
+
class << self
|
|
7
|
+
# matches inputs like "key(1i)"
|
|
8
|
+
GROUPED_INPUT_PATTERN = /
|
|
9
|
+
\A
|
|
10
|
+
(?<key>.+) # extracts "key"
|
|
11
|
+
\((?<index>\d+)i\) # extracts "1"
|
|
12
|
+
\z
|
|
13
|
+
/x.freeze
|
|
14
|
+
private_constant :GROUPED_INPUT_PATTERN
|
|
15
|
+
|
|
16
|
+
# Checking `syscall` is the result of what appears to be a bug in Ruby.
|
|
17
|
+
# https://bugs.ruby-lang.org/issues/15597
|
|
18
|
+
def reserved?(name)
|
|
19
|
+
name.to_s.start_with?('_interaction_') ||
|
|
20
|
+
name == :syscall ||
|
|
21
|
+
Base.method_defined?(name) ||
|
|
22
|
+
Base.private_method_defined?(name)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def process(inputs)
|
|
26
|
+
inputs.stringify_keys.sort.each_with_object({}) do |(k, v), h|
|
|
27
|
+
next if reserved?(k)
|
|
28
|
+
|
|
29
|
+
if (group = GROUPED_INPUT_PATTERN.match(k))
|
|
30
|
+
assign_to_grouped_input!(h, group[:key], group[:index], v)
|
|
31
|
+
else
|
|
32
|
+
h[k.to_sym] = v
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def assign_to_grouped_input!(inputs, key, index, value)
|
|
40
|
+
key = key.to_sym
|
|
41
|
+
|
|
42
|
+
inputs[key] = GroupedInput.new unless inputs[key].is_a?(GroupedInput)
|
|
43
|
+
inputs[key][index] = value
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def initialize
|
|
48
|
+
@groups = {}
|
|
49
|
+
@groups.default_proc = ->(hash, key) { hash[key] = [] }
|
|
50
|
+
|
|
51
|
+
super(@inputs = {})
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Associates the `value` with the `key`. Allows the `key`/`value` pair to
|
|
55
|
+
# be associated with one or more groups.
|
|
56
|
+
#
|
|
57
|
+
# @example
|
|
58
|
+
# inputs.store(:key, :value)
|
|
59
|
+
# # => :value
|
|
60
|
+
# inputs.store(:key, :value, %i[a b])
|
|
61
|
+
# # => :value
|
|
62
|
+
#
|
|
63
|
+
# @param key [Object] The key to store the value under.
|
|
64
|
+
# @param value [Object] The value to store.
|
|
65
|
+
# @param groups [Array<Object>] The groups to store the pair under.
|
|
66
|
+
#
|
|
67
|
+
# @return [Object] value
|
|
68
|
+
def store(key, value, groups = [])
|
|
69
|
+
groups.each do |group|
|
|
70
|
+
@groups[group] << key
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
super(key, value)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns inputs from the group name given.
|
|
77
|
+
#
|
|
78
|
+
# @example
|
|
79
|
+
# inputs.group(:a)
|
|
80
|
+
# # => {key: :value}
|
|
81
|
+
#
|
|
82
|
+
# @param name [Object] Name of the group to return.
|
|
83
|
+
#
|
|
84
|
+
# @return [Hash] Inputs from the group name given.
|
|
85
|
+
def group(name)
|
|
86
|
+
@inputs.select { |k, _| @groups[name].include?(k) }
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
ja:
|
|
2
|
+
active_interaction:
|
|
3
|
+
errors:
|
|
4
|
+
messages:
|
|
5
|
+
invalid: は無効です
|
|
6
|
+
invalid_nested: は無効なネストされた値です (%{name} => %{value})
|
|
7
|
+
invalid_type: は無効な %{type} です
|
|
8
|
+
missing: が必要です
|
|
9
|
+
types:
|
|
10
|
+
array: 配列
|
|
11
|
+
boolean: ブール
|
|
12
|
+
date: 日付
|
|
13
|
+
date_time: 日時
|
|
14
|
+
decimal: 10進数
|
|
15
|
+
file: ファイル
|
|
16
|
+
float: 浮動小数点数
|
|
17
|
+
hash: ハッシュ
|
|
18
|
+
integer: 整数
|
|
19
|
+
interface: インターフェース
|
|
20
|
+
object: オブジェクト
|
|
21
|
+
record: レコード
|
|
22
|
+
string: 文字
|
|
23
|
+
symbol: シンボル
|
|
24
|
+
time: 時間
|
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module ActiveInteraction
|
|
5
4
|
# Groups inputs ending in "(*N*i)" into {GroupedInput}.
|
|
6
5
|
#
|
|
7
|
-
# @since 1.2.0
|
|
8
|
-
#
|
|
9
6
|
# @private
|
|
10
7
|
module InputProcessor
|
|
11
8
|
class << self
|
|
12
|
-
GROUPED_INPUT_PATTERN = /\A(.+)\((\d+)i\)\z
|
|
9
|
+
GROUPED_INPUT_PATTERN = /\A(.+)\((\d+)i\)\z/.freeze
|
|
13
10
|
private_constant :GROUPED_INPUT_PATTERN
|
|
14
11
|
|
|
15
12
|
# Checking `syscall` is the result of what appears to be a bug in Ruby.
|
|
@@ -17,8 +14,14 @@ module ActiveInteraction
|
|
|
17
14
|
def reserved?(name)
|
|
18
15
|
name.to_s.start_with?('_interaction_') ||
|
|
19
16
|
name == :syscall ||
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
(
|
|
18
|
+
Base.method_defined?(name) &&
|
|
19
|
+
!Object.method_defined?(name)
|
|
20
|
+
) ||
|
|
21
|
+
(
|
|
22
|
+
Base.private_method_defined?(name) &&
|
|
23
|
+
!Object.private_method_defined?(name)
|
|
24
|
+
)
|
|
22
25
|
end
|
|
23
26
|
|
|
24
27
|
def process(inputs)
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
1
|
# frozen_string_literal: true
|
|
3
2
|
|
|
4
3
|
module ActiveInteraction
|
|
@@ -12,14 +11,13 @@ module ActiveInteraction
|
|
|
12
11
|
# @param inputs [Hash{Symbol => Object}]
|
|
13
12
|
def validate(context, filters, inputs)
|
|
14
13
|
filters.each_with_object([]) do |(name, filter), errors|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
end
|
|
14
|
+
filter.clean(inputs[name], context)
|
|
15
|
+
rescue NoDefaultError
|
|
16
|
+
nil
|
|
17
|
+
rescue InvalidNestedValueError,
|
|
18
|
+
InvalidValueError,
|
|
19
|
+
MissingValueError => e
|
|
20
|
+
errors << error_args(filter, e)
|
|
23
21
|
end
|
|
24
22
|
end
|
|
25
23
|
|
|
@@ -28,10 +26,9 @@ module ActiveInteraction
|
|
|
28
26
|
def error_args(filter, error)
|
|
29
27
|
case error
|
|
30
28
|
when InvalidNestedValueError
|
|
31
|
-
[filter.name, :invalid_nested,
|
|
32
|
-
name: error.filter_name.inspect, value: error.input_value.inspect]
|
|
29
|
+
[filter.name, :invalid_nested, { name: error.filter_name.inspect, value: error.input_value.inspect }]
|
|
33
30
|
when InvalidValueError
|
|
34
|
-
[filter.name, :invalid_type, type: type(filter)]
|
|
31
|
+
[filter.name, :invalid_type, { type: type(filter) }]
|
|
35
32
|
when MissingValueError
|
|
36
33
|
[filter.name, :missing]
|
|
37
34
|
end
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
# coding: utf-8
|
|
2
|
-
|
|
3
1
|
require 'spec_helper'
|
|
4
2
|
require 'action_controller'
|
|
5
3
|
|
|
@@ -24,6 +22,12 @@ InterruptInteraction = Class.new(TestInteraction) do
|
|
|
24
22
|
class: Object,
|
|
25
23
|
default: nil
|
|
26
24
|
|
|
25
|
+
# NOTE: the relative position between this method
|
|
26
|
+
# and the compose line should be preserved.
|
|
27
|
+
def self.composition_location
|
|
28
|
+
"#{__FILE__}:#{__LINE__ + 4}:in `execute'"
|
|
29
|
+
end
|
|
30
|
+
|
|
27
31
|
def execute
|
|
28
32
|
compose(AddInteraction, x: x, y: z)
|
|
29
33
|
end
|
|
@@ -51,7 +55,7 @@ describe ActiveInteraction::Base do
|
|
|
51
55
|
end
|
|
52
56
|
|
|
53
57
|
context 'with non-hash inputs' do
|
|
54
|
-
let(:inputs) { [[
|
|
58
|
+
let(:inputs) { [%i[k v]] }
|
|
55
59
|
|
|
56
60
|
it 'raises an error' do
|
|
57
61
|
expect { interaction }.to raise_error ArgumentError
|
|
@@ -371,6 +375,13 @@ describe ActiveInteraction::Base do
|
|
|
371
375
|
expect(outcome.errors.details)
|
|
372
376
|
.to eql(x: [{ error: :missing }], base: [{ error: 'Y is required' }])
|
|
373
377
|
end
|
|
378
|
+
|
|
379
|
+
it 'has the correct backtrace' do
|
|
380
|
+
described_class.run!(inputs)
|
|
381
|
+
rescue ActiveInteraction::InvalidInteractionError => e
|
|
382
|
+
expect(e.backtrace)
|
|
383
|
+
.to include(InterruptInteraction.composition_location)
|
|
384
|
+
end
|
|
374
385
|
end
|
|
375
386
|
end
|
|
376
387
|
|
|
@@ -505,6 +516,79 @@ describe ActiveInteraction::Base do
|
|
|
505
516
|
expect(result).to be false
|
|
506
517
|
end
|
|
507
518
|
end
|
|
519
|
+
|
|
520
|
+
context 'nested array values' do
|
|
521
|
+
let(:described_class) do
|
|
522
|
+
Class.new(TestInteraction) do
|
|
523
|
+
array :x do
|
|
524
|
+
hash do
|
|
525
|
+
boolean :y, default: true
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
def execute; end
|
|
530
|
+
end
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
context 'has a positive index' do
|
|
534
|
+
it 'returns true if found' do
|
|
535
|
+
described_class.class_exec do
|
|
536
|
+
def execute
|
|
537
|
+
given?(:x, 0, :y)
|
|
538
|
+
end
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
inputs[:x] = [{ y: true }]
|
|
542
|
+
expect(result).to be true
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
it 'returns false if not found' do
|
|
546
|
+
described_class.class_exec do
|
|
547
|
+
def execute
|
|
548
|
+
given?(:x, 0, :y)
|
|
549
|
+
end
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
inputs[:x] = []
|
|
553
|
+
expect(result).to be false
|
|
554
|
+
end
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
context 'has a negative index' do
|
|
558
|
+
it 'returns true if found' do
|
|
559
|
+
described_class.class_exec do
|
|
560
|
+
def execute
|
|
561
|
+
given?(:x, -1, :y)
|
|
562
|
+
end
|
|
563
|
+
end
|
|
564
|
+
|
|
565
|
+
inputs[:x] = [{ y: true }]
|
|
566
|
+
expect(result).to be true
|
|
567
|
+
end
|
|
568
|
+
|
|
569
|
+
it 'returns false if not found' do
|
|
570
|
+
described_class.class_exec do
|
|
571
|
+
def execute
|
|
572
|
+
given?(:x, -1, :y)
|
|
573
|
+
end
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
inputs[:x] = []
|
|
577
|
+
expect(result).to be false
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
it 'returns false if you go too far' do
|
|
582
|
+
described_class.class_exec do
|
|
583
|
+
def execute
|
|
584
|
+
given?(:x, 10, :y)
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
inputs[:x] = [{}]
|
|
589
|
+
expect(result).to be false
|
|
590
|
+
end
|
|
591
|
+
end
|
|
508
592
|
end
|
|
509
593
|
|
|
510
594
|
context 'inheritance' do
|
|
@@ -555,32 +639,6 @@ describe ActiveInteraction::Base do
|
|
|
555
639
|
end
|
|
556
640
|
end
|
|
557
641
|
|
|
558
|
-
context 'predicates' do
|
|
559
|
-
let(:described_class) { InteractionWithFilter }
|
|
560
|
-
|
|
561
|
-
it 'responds to the predicate' do
|
|
562
|
-
expect(interaction.respond_to?(:thing?)).to be_truthy
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
context 'without a value' do
|
|
566
|
-
it 'returns false' do
|
|
567
|
-
expect(interaction.thing?).to be_falsey
|
|
568
|
-
end
|
|
569
|
-
end
|
|
570
|
-
|
|
571
|
-
context 'with a value' do
|
|
572
|
-
let(:thing) { rand }
|
|
573
|
-
|
|
574
|
-
before do
|
|
575
|
-
inputs[:thing] = thing
|
|
576
|
-
end
|
|
577
|
-
|
|
578
|
-
it 'returns true' do
|
|
579
|
-
expect(interaction.thing?).to be_truthy
|
|
580
|
-
end
|
|
581
|
-
end
|
|
582
|
-
end
|
|
583
|
-
|
|
584
642
|
describe '.import_filters' do
|
|
585
643
|
shared_context 'import_filters context' do |only, except|
|
|
586
644
|
let(:klass) { AddInteraction }
|
|
@@ -599,9 +657,11 @@ describe ActiveInteraction::Base do
|
|
|
599
657
|
include_context 'import_filters context', only, except
|
|
600
658
|
|
|
601
659
|
it 'imports the filters' do
|
|
602
|
-
expect(described_class.filters).to eql
|
|
603
|
-
.
|
|
604
|
-
|
|
660
|
+
expect(described_class.filters).to eql(
|
|
661
|
+
klass.filters
|
|
662
|
+
.select { |k, _| only.nil? ? true : [*only].include?(k) }
|
|
663
|
+
.reject { |k, _| except.nil? ? false : [*except].include?(k) }
|
|
664
|
+
)
|
|
605
665
|
end
|
|
606
666
|
|
|
607
667
|
it 'does not modify the source' do
|
|
@@ -610,11 +670,11 @@ describe ActiveInteraction::Base do
|
|
|
610
670
|
expect(klass.filters).to eql filters
|
|
611
671
|
end
|
|
612
672
|
|
|
613
|
-
it 'responds to readers
|
|
673
|
+
it 'responds to readers and writers' do
|
|
614
674
|
instance = described_class.new
|
|
615
675
|
|
|
616
|
-
described_class.filters.
|
|
617
|
-
[name, "#{name}="
|
|
676
|
+
described_class.filters.each_key do |name|
|
|
677
|
+
[name, "#{name}="].each do |method|
|
|
618
678
|
expect(instance).to respond_to method
|
|
619
679
|
end
|
|
620
680
|
end
|