active_interaction 4.1.0 → 5.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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +128 -1
  3. data/README.md +63 -28
  4. data/lib/active_interaction/array_input.rb +77 -0
  5. data/lib/active_interaction/base.rb +14 -98
  6. data/lib/active_interaction/concerns/active_recordable.rb +3 -3
  7. data/lib/active_interaction/concerns/missable.rb +2 -2
  8. data/lib/active_interaction/errors.rb +6 -88
  9. data/lib/active_interaction/exceptions.rb +47 -0
  10. data/lib/active_interaction/filter/column.rb +59 -0
  11. data/lib/active_interaction/filter/error.rb +40 -0
  12. data/lib/active_interaction/filter.rb +44 -53
  13. data/lib/active_interaction/filters/abstract_date_time_filter.rb +9 -6
  14. data/lib/active_interaction/filters/abstract_numeric_filter.rb +7 -3
  15. data/lib/active_interaction/filters/array_filter.rb +34 -6
  16. data/lib/active_interaction/filters/boolean_filter.rb +4 -3
  17. data/lib/active_interaction/filters/date_filter.rb +1 -1
  18. data/lib/active_interaction/filters/date_time_filter.rb +1 -1
  19. data/lib/active_interaction/filters/decimal_filter.rb +1 -1
  20. data/lib/active_interaction/filters/float_filter.rb +1 -1
  21. data/lib/active_interaction/filters/hash_filter.rb +23 -15
  22. data/lib/active_interaction/filters/integer_filter.rb +1 -1
  23. data/lib/active_interaction/filters/interface_filter.rb +12 -12
  24. data/lib/active_interaction/filters/object_filter.rb +9 -3
  25. data/lib/active_interaction/filters/record_filter.rb +21 -11
  26. data/lib/active_interaction/filters/string_filter.rb +1 -1
  27. data/lib/active_interaction/filters/symbol_filter.rb +1 -1
  28. data/lib/active_interaction/filters/time_filter.rb +4 -4
  29. data/lib/active_interaction/hash_input.rb +43 -0
  30. data/lib/active_interaction/input.rb +23 -0
  31. data/lib/active_interaction/inputs.rb +157 -46
  32. data/lib/active_interaction/locale/en.yml +0 -1
  33. data/lib/active_interaction/locale/fr.yml +0 -1
  34. data/lib/active_interaction/locale/it.yml +0 -1
  35. data/lib/active_interaction/locale/ja.yml +0 -1
  36. data/lib/active_interaction/locale/pt-BR.yml +0 -1
  37. data/lib/active_interaction/modules/validation.rb +6 -17
  38. data/lib/active_interaction/version.rb +1 -1
  39. data/lib/active_interaction.rb +43 -36
  40. data/spec/active_interaction/array_input_spec.rb +166 -0
  41. data/spec/active_interaction/base_spec.rb +15 -240
  42. data/spec/active_interaction/concerns/active_modelable_spec.rb +3 -3
  43. data/spec/active_interaction/concerns/active_recordable_spec.rb +7 -7
  44. data/spec/active_interaction/concerns/hashable_spec.rb +8 -8
  45. data/spec/active_interaction/concerns/missable_spec.rb +9 -9
  46. data/spec/active_interaction/concerns/runnable_spec.rb +34 -32
  47. data/spec/active_interaction/errors_spec.rb +60 -43
  48. data/spec/active_interaction/{filter_column_spec.rb → filter/column_spec.rb} +3 -10
  49. data/spec/active_interaction/filter_spec.rb +6 -6
  50. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +2 -2
  51. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +2 -2
  52. data/spec/active_interaction/filters/array_filter_spec.rb +99 -16
  53. data/spec/active_interaction/filters/boolean_filter_spec.rb +12 -11
  54. data/spec/active_interaction/filters/date_filter_spec.rb +32 -27
  55. data/spec/active_interaction/filters/date_time_filter_spec.rb +34 -29
  56. data/spec/active_interaction/filters/decimal_filter_spec.rb +20 -18
  57. data/spec/active_interaction/filters/file_filter_spec.rb +7 -7
  58. data/spec/active_interaction/filters/float_filter_spec.rb +19 -17
  59. data/spec/active_interaction/filters/hash_filter_spec.rb +16 -18
  60. data/spec/active_interaction/filters/integer_filter_spec.rb +24 -22
  61. data/spec/active_interaction/filters/interface_filter_spec.rb +105 -82
  62. data/spec/active_interaction/filters/object_filter_spec.rb +52 -36
  63. data/spec/active_interaction/filters/record_filter_spec.rb +61 -39
  64. data/spec/active_interaction/filters/string_filter_spec.rb +7 -7
  65. data/spec/active_interaction/filters/symbol_filter_spec.rb +6 -6
  66. data/spec/active_interaction/filters/time_filter_spec.rb +57 -34
  67. data/spec/active_interaction/hash_input_spec.rb +58 -0
  68. data/spec/active_interaction/i18n_spec.rb +22 -17
  69. data/spec/active_interaction/inputs_spec.rb +167 -23
  70. data/spec/active_interaction/integration/array_interaction_spec.rb +3 -7
  71. data/spec/active_interaction/modules/validation_spec.rb +8 -31
  72. data/spec/spec_helper.rb +8 -0
  73. data/spec/support/concerns.rb +2 -2
  74. data/spec/support/filters.rb +27 -51
  75. data/spec/support/interactions.rb +4 -4
  76. metadata +40 -91
  77. data/lib/active_interaction/filter_column.rb +0 -57
@@ -47,34 +47,34 @@ module ActiveInteraction
47
47
  "constant #{const_name.inspect} does not exist"
48
48
  end
49
49
 
50
- def matches?(object)
51
- return false if object.nil?
52
- return matches_methods?(object) if options.key?(:methods)
50
+ def matches?(value)
51
+ return false if value == nil # rubocop:disable Style/NilComparison
52
+ return matches_methods?(value) if options.key?(:methods)
53
53
 
54
54
  const = from
55
- if checking_class_inheritance?(object, const)
56
- class_inherits_from?(object, const)
55
+ if checking_class_inheritance?(value, const)
56
+ class_inherits_from?(value, const)
57
57
  else
58
- singleton_ancestor?(object, const)
58
+ singleton_ancestor?(value, const)
59
59
  end
60
60
  rescue NoMethodError
61
61
  false
62
62
  end
63
63
 
64
- def matches_methods?(object)
65
- options[:methods].all? { |method| object.respond_to?(method) }
64
+ def matches_methods?(value)
65
+ options[:methods].all? { |method| value.respond_to?(method) }
66
66
  end
67
67
 
68
- def checking_class_inheritance?(object, from)
69
- object.is_a?(Class) && from.is_a?(Class)
68
+ def checking_class_inheritance?(value, from)
69
+ value.is_a?(Class) && from.is_a?(Class)
70
70
  end
71
71
 
72
72
  def class_inherits_from?(klass, inherits_from)
73
73
  klass != inherits_from && klass.ancestors.include?(inherits_from)
74
74
  end
75
75
 
76
- def singleton_ancestor?(object, from)
77
- object.class != from && object.singleton_class.ancestors.include?(from)
76
+ def singleton_ancestor?(value, from)
77
+ value.class != from && value.singleton_class.ancestors.include?(from)
78
78
  end
79
79
  end
80
80
  end
@@ -38,19 +38,25 @@ module ActiveInteraction
38
38
  end
39
39
 
40
40
  def matches?(value)
41
+ return false if value == nil # rubocop:disable Style/NilComparison
42
+
41
43
  value.class <= klass
42
44
  rescue NoMethodError
43
45
  false
44
46
  end
45
47
 
46
48
  def convert(value)
47
- converter(value).tap do |result|
48
- raise InvalidValueError if result.nil?
49
+ result = converter(value)
50
+
51
+ if result.nil?
52
+ [value, Filter::Error.new(self, :invalid_type)]
53
+ else
54
+ [result, nil]
49
55
  end
50
56
  rescue StandardError => e
51
57
  raise e if e.is_a?(InvalidConverterError)
52
58
 
53
- raise InvalidValueError
59
+ [value, Filter::Error.new(self, :invalid_type)]
54
60
  end
55
61
 
56
62
  def converter(value)
@@ -4,7 +4,9 @@ module ActiveInteraction
4
4
  class Base # rubocop:disable Lint/EmptyClass
5
5
  # @!method self.record(*attributes, options = {})
6
6
  # Creates accessors for the attributes and ensures that values passed to
7
- # the attributes are the correct class.
7
+ # the attributes are the correct class. Blank strings passed in will be
8
+ # treated as `nil` and the `finder` will not be called.
9
+
8
10
  #
9
11
  # @!macro filter_method_params
10
12
  # @option options [Class, String, Symbol] :class (use the attribute name)
@@ -44,20 +46,28 @@ module ActiveInteraction
44
46
  end
45
47
 
46
48
  def convert(value)
47
- finder = options.fetch(:finder, :find)
48
- find(klass, value, finder)
49
- end
49
+ return [nil, nil] if blank_string?(value)
50
50
 
51
- def find(klass, value, finder)
52
- result = klass.public_send(finder, value)
51
+ finder = options.fetch(:finder, :find)
52
+ result = find(klass, value, finder)
53
53
 
54
- raise InvalidValueError if result.nil?
54
+ if result.nil?
55
+ [value, Filter::Error.new(self, :invalid_type)]
56
+ else
57
+ [result, nil]
58
+ end
59
+ end
55
60
 
56
- result
57
- rescue StandardError => e
58
- raise e if e.is_a?(InvalidConverterError)
61
+ def blank_string?(value)
62
+ value.is_a?(String) && value.blank?
63
+ rescue NoMethodError # BasicObject
64
+ false
65
+ end
59
66
 
60
- raise InvalidValueError
67
+ def find(klass, value, finder)
68
+ klass.public_send(finder, value)
69
+ rescue StandardError
70
+ nil
61
71
  end
62
72
  end
63
73
  end
@@ -38,7 +38,7 @@ module ActiveInteraction
38
38
 
39
39
  def convert(value)
40
40
  if value.respond_to?(:to_str)
41
- value.to_str
41
+ [value.to_str, nil]
42
42
  else
43
43
  super
44
44
  end
@@ -26,7 +26,7 @@ module ActiveInteraction
26
26
 
27
27
  def convert(value)
28
28
  if value.respond_to?(:to_sym)
29
- value.to_sym
29
+ [value.to_sym, nil]
30
30
  else
31
31
  super
32
32
  end
@@ -6,9 +6,9 @@ module ActiveInteraction
6
6
  # Creates accessors for the attributes and ensures that values passed to
7
7
  # the attributes are Times. Numeric values are processed using `at`.
8
8
  # Strings are processed using `parse` unless the format option is
9
- # given, in which case they will be processed with `strptime`. If
10
- # `Time.zone` is available it will be used so that the values are time
11
- # zone aware.
9
+ # given, in which case they will be processed with `strptime`. Blank
10
+ # strings are treated as a `nil` value. If `Time.zone` is available it
11
+ # will be used so that the values are time zone aware.
12
12
  #
13
13
  # @!macro filter_method_params
14
14
  # @option options [String] :format parse strings using this format string
@@ -59,7 +59,7 @@ module ActiveInteraction
59
59
  value = value.to_int if value.respond_to?(:to_int)
60
60
 
61
61
  if value.is_a?(Numeric)
62
- klass.at(value)
62
+ [klass.at(value), nil]
63
63
  else
64
64
  super
65
65
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveInteraction
4
+ # Represents a processed hash input.
5
+ class HashInput < Input
6
+ # @private
7
+ def initialize(filter, value: nil, error: nil, children: {})
8
+ super(filter, value: value, error: error)
9
+
10
+ @children = children
11
+ end
12
+
13
+ # @overload children
14
+ # Child inputs if nested filters are used.
15
+ #
16
+ # @return [Hash{ Symbol => Input, ArrayInput, HashInput }]
17
+ attr_reader :children
18
+
19
+ # Any errors that occurred during processing.
20
+ #
21
+ # @return [Filter::Error]
22
+ def errors
23
+ return @errors if defined?(@errors)
24
+
25
+ return @errors = super if @error
26
+
27
+ child_errors = get_errors(children)
28
+
29
+ return @errors = super if child_errors.empty?
30
+
31
+ @errors ||=
32
+ child_errors.map do |error|
33
+ Filter::Error.new(error.filter, error.type, name: :"#{@filter.name}.#{error.name}")
34
+ end.freeze
35
+ end
36
+
37
+ private
38
+
39
+ def get_errors(children)
40
+ children.values.flat_map(&:errors)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveInteraction
4
+ # Represents a processed input.
5
+ class Input
6
+ # @private
7
+ def initialize(filter, value: nil, error: nil)
8
+ @filter = filter
9
+ @value = value
10
+ @error = error
11
+ end
12
+
13
+ # The processed input value.
14
+ attr_reader :value
15
+
16
+ # Any errors that occurred during processing.
17
+ #
18
+ # @return [Filter::Error]
19
+ def errors
20
+ @errors ||= Array(@error)
21
+ end
22
+ end
23
+ end
@@ -1,24 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
4
+
3
5
  module ActiveInteraction
4
6
  # 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
7
+ class Inputs
8
+ include Enumerable
9
+ extend Forwardable
15
10
 
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
11
+ # matches inputs like "key(1i)"
12
+ GROUPED_INPUT_PATTERN = /
13
+ \A
14
+ (?<key>.+) # extracts "key"
15
+ \((?<index>\d+)i\) # extracts "1"
16
+ \z
17
+ /x.freeze
18
+ private_constant :GROUPED_INPUT_PATTERN
21
19
 
20
+ class << self
22
21
  # Checking `syscall` is the result of what appears to be a bug in Ruby.
23
22
  # https://bugs.ruby-lang.org/issues/15597
24
23
  # @private
@@ -34,47 +33,159 @@ module ActiveInteraction
34
33
  !Object.private_method_defined?(name)
35
34
  )
36
35
  end
36
+ end
37
37
 
38
- # @param inputs [Hash, ActionController::Parameters, ActiveInteraction::Inputs] Attribute values to set.
39
- #
40
- # @private
41
- def process(inputs)
42
- normalize_inputs!(inputs)
43
- .stringify_keys
44
- .sort
45
- .each_with_object({}) do |(k, v), h|
46
- next if reserved?(k)
47
-
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
53
- end
38
+ # @private
39
+ def initialize(raw_inputs, base)
40
+ @base = base
41
+ @normalized_inputs = normalize(raw_inputs)
42
+ @inputs = base.class.filters.each_with_object({}) do |(name, filter), inputs|
43
+ inputs[name] = filter.process(@normalized_inputs[name], base)
44
+
45
+ yield name, inputs[name] if block_given?
54
46
  end
47
+ end
55
48
 
56
- private
49
+ # @private
50
+ def normalized
51
+ @normalized_inputs
52
+ end
57
53
 
58
- def normalize_inputs!(inputs)
59
- return inputs if inputs.is_a?(Hash) || inputs.is_a?(Inputs)
54
+ # Turn the inputs into a Hash.
55
+ #
56
+ # @return [Hash]
57
+ def to_h
58
+ @to_h ||= @inputs.transform_values(&:value).freeze
59
+ end
60
60
 
61
- parameters = 'ActionController::Parameters'
62
- klass = parameters.safe_constantize
63
- return inputs.to_unsafe_h if klass && inputs.is_a?(klass)
61
+ def_delegators :to_h,
62
+ :[],
63
+ :dig,
64
+ :each,
65
+ :each_key,
66
+ :each_pair,
67
+ :each_value,
68
+ :empty?,
69
+ :except,
70
+ :fetch,
71
+ :fetch_values,
72
+ :filter,
73
+ :flatten,
74
+ :has_key?,
75
+ :has_value?,
76
+ :include?,
77
+ :inspect,
78
+ :key,
79
+ :key?,
80
+ :keys,
81
+ :length,
82
+ :member?,
83
+ :merge,
84
+ :rassoc,
85
+ :reject,
86
+ :select,
87
+ :size,
88
+ :slice,
89
+ :store,
90
+ :to_a,
91
+ :to_s,
92
+ :value?,
93
+ :values,
94
+ :values_at
64
95
 
65
- raise ArgumentError, "inputs must be a hash or #{parameters}"
66
- end
96
+ # Returns `true` if the given key was in the hash passed to {.run}.
97
+ # Otherwise returns `false`. Use this to figure out if an input was given,
98
+ # even if it was `nil`. Keys within nested hash filter can also be checked
99
+ # by passing them in series. Arrays can be checked in the same manor as
100
+ # hashes by passing an index.
101
+ #
102
+ # @example
103
+ # class Example < ActiveInteraction::Base
104
+ # integer :x, default: nil
105
+ # def execute; given?(:x) end
106
+ # end
107
+ # Example.run!() # => false
108
+ # Example.run!(x: nil) # => true
109
+ # Example.run!(x: rand) # => true
110
+ #
111
+ # @example Nested checks
112
+ # class Example < ActiveInteraction::Base
113
+ # hash :x, default: {} do
114
+ # integer :y, default: nil
115
+ # end
116
+ # array :a, default: [] do
117
+ # integer
118
+ # end
119
+ # def execute; given?(:x, :y) || given?(:a, 2) end
120
+ # end
121
+ # Example.run!() # => false
122
+ # Example.run!(x: nil) # => false
123
+ # Example.run!(x: {}) # => false
124
+ # Example.run!(x: { y: nil }) # => true
125
+ # Example.run!(x: { y: rand }) # => true
126
+ # Example.run!(a: [1, 2]) # => false
127
+ # Example.run!(a: [1, 2, 3]) # => true
128
+ #
129
+ # @param input [#to_sym]
130
+ #
131
+ # @return [Boolean]
132
+ #
133
+ # rubocop:disable all
134
+ def given?(input, *rest)
135
+ filter_level = @base.class
136
+ input_level = @normalized_inputs
67
137
 
68
- def assign_to_grouped_input!(inputs, key, index, value)
69
- key = key.to_sym
138
+ [input, *rest].each do |key_or_index|
139
+ if key_or_index.is_a?(Symbol) || key_or_index.is_a?(String)
140
+ key = key_or_index.to_sym
141
+ key_to_s = key_or_index.to_s
142
+ filter_level = filter_level.filters[key]
70
143
 
71
- inputs[key] = GroupedInput.new unless inputs[key].is_a?(GroupedInput)
72
- inputs[key][index] = value
73
- end
144
+ break false if filter_level.nil? || input_level.nil?
145
+ break false unless input_level.key?(key) || input_level.key?(key_to_s)
146
+
147
+ input_level = input_level[key] || input_level[key_to_s]
148
+ else
149
+ index = key_or_index
150
+ filter_level = filter_level.filters.first.last
151
+
152
+ break false if filter_level.nil? || input_level.nil?
153
+ break false unless index.between?(-input_level.size, input_level.size - 1)
154
+
155
+ input_level = input_level[index]
156
+ end
157
+ end && true
74
158
  end
159
+ # rubocop:enable all
160
+
161
+ private
162
+
163
+ def normalize(inputs)
164
+ convert(inputs)
165
+ .sort
166
+ .each_with_object({}) do |(k, v), h|
167
+ next if self.class.reserved?(k)
168
+
169
+ if (group = GROUPED_INPUT_PATTERN.match(k))
170
+ assign_to_grouped_input!(h, group[:key], group[:index], v)
171
+ else
172
+ h[k.to_sym] = v
173
+ end
174
+ end
175
+ end
176
+
177
+ def convert(inputs)
178
+ return inputs.stringify_keys if inputs.is_a?(Hash)
179
+ return inputs.to_unsafe_h.stringify_keys if inputs.is_a?(ActionController::Parameters)
180
+
181
+ raise ArgumentError, 'inputs must be a hash or ActionController::Parameters'
182
+ end
183
+
184
+ def assign_to_grouped_input!(inputs, key, index, value)
185
+ key = key.to_sym
75
186
 
76
- def initialize(inputs = {})
77
- super(inputs)
187
+ inputs[key] = GroupedInput.new unless inputs[key].is_a?(GroupedInput)
188
+ inputs[key][index] = value
78
189
  end
79
190
  end
80
191
  end
@@ -3,7 +3,6 @@ en:
3
3
  errors:
4
4
  messages:
5
5
  invalid: is invalid
6
- invalid_nested: has an invalid nested value (%{name} => %{value})
7
6
  invalid_type: is not a valid %{type}
8
7
  missing: is required
9
8
  types:
@@ -3,7 +3,6 @@ fr:
3
3
  errors:
4
4
  messages:
5
5
  invalid: est invalide
6
- invalid_nested: contient une valeur imbriquée invalide (%{name} => %{value})
7
6
  invalid_type: a un type invalide (%{type})
8
7
  missing: est obligatoire
9
8
  types:
@@ -3,7 +3,6 @@ it:
3
3
  errors:
4
4
  messages:
5
5
  invalid: non è valido
6
- invalid_nested: ha un valore nidificato non valido (%{name} => %{value})
7
6
  invalid_type: non è di tipo %{type}
8
7
  missing: è obbligatorio
9
8
  types:
@@ -3,7 +3,6 @@ ja:
3
3
  errors:
4
4
  messages:
5
5
  invalid: は無効です
6
- invalid_nested: は無効なネストされた値です (%{name} => %{value})
7
6
  invalid_type: は無効な %{type} です
8
7
  missing: が必要です
9
8
  types:
@@ -3,7 +3,6 @@ pt-BR:
3
3
  errors:
4
4
  messages:
5
5
  invalid: é inválido
6
- invalid_nested: possui um valor aninhado inválido (%{name} => %{value})
7
6
  invalid_type: não é um(a) %{type} válido(a)
8
7
  missing: é obrigatório
9
8
  types:
@@ -8,26 +8,15 @@ module ActiveInteraction
8
8
  class << self
9
9
  # @param context [Base]
10
10
  # @param filters [Hash{Symbol => Filter}]
11
- # @param inputs [Hash{Symbol => Object}]
11
+ # @param inputs [Inputs]
12
12
  def validate(context, filters, inputs)
13
13
  filters.each_with_object([]) do |(name, filter), errors|
14
- filter.clean(inputs[name], context)
15
- rescue NoDefaultError
16
- nil
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]
23
- end
24
- end
14
+ input = filter.process(inputs[name], context)
25
15
 
26
- private
27
-
28
- # @param filter [Filter]
29
- def type(filter)
30
- I18n.translate("#{Base.i18n_scope}.types.#{filter.class.slug}")
16
+ input.errors.each do |error|
17
+ errors << [error.name, error.type, error.options]
18
+ end
19
+ end
31
20
  end
32
21
  end
33
22
  end
@@ -4,5 +4,5 @@ module ActiveInteraction
4
4
  # The version number.
5
5
  #
6
6
  # @return [Gem::Version]
7
- VERSION = Gem::Version.new('4.1.0')
7
+ VERSION = Gem::Version.new('5.0.0')
8
8
  end
@@ -1,7 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'active_model'
4
- require 'active_support/hash_with_indifferent_access'
4
+ require 'active_record'
5
+ require 'active_support/core_ext/hash/indifferent_access'
6
+ require 'action_controller'
5
7
 
6
8
  # Manage application specific business logic.
7
9
  #
@@ -10,41 +12,46 @@ require 'active_support/hash_with_indifferent_access'
10
12
  module ActiveInteraction
11
13
  end
12
14
 
13
- require 'active_interaction/version'
14
- require 'active_interaction/errors'
15
-
16
- require 'active_interaction/concerns/active_modelable'
17
- require 'active_interaction/concerns/active_recordable'
18
- require 'active_interaction/concerns/hashable'
19
- require 'active_interaction/concerns/missable'
20
- require 'active_interaction/concerns/runnable'
21
-
22
- require 'active_interaction/grouped_input'
23
- require 'active_interaction/inputs'
24
-
25
- require 'active_interaction/modules/validation'
26
-
27
- require 'active_interaction/filter_column'
28
- require 'active_interaction/filter'
29
- require 'active_interaction/filters/interface_filter'
30
- require 'active_interaction/filters/abstract_date_time_filter'
31
- require 'active_interaction/filters/abstract_numeric_filter'
32
- require 'active_interaction/filters/array_filter'
33
- require 'active_interaction/filters/boolean_filter'
34
- require 'active_interaction/filters/date_filter'
35
- require 'active_interaction/filters/date_time_filter'
36
- require 'active_interaction/filters/decimal_filter'
37
- require 'active_interaction/filters/file_filter'
38
- require 'active_interaction/filters/float_filter'
39
- require 'active_interaction/filters/hash_filter'
40
- require 'active_interaction/filters/integer_filter'
41
- require 'active_interaction/filters/object_filter'
42
- require 'active_interaction/filters/record_filter'
43
- require 'active_interaction/filters/string_filter'
44
- require 'active_interaction/filters/symbol_filter'
45
- require 'active_interaction/filters/time_filter'
46
-
47
- require 'active_interaction/base'
15
+ require_relative 'active_interaction/version'
16
+ require_relative 'active_interaction/exceptions'
17
+ require_relative 'active_interaction/errors'
18
+
19
+ require_relative 'active_interaction/concerns/active_modelable'
20
+ require_relative 'active_interaction/concerns/active_recordable'
21
+ require_relative 'active_interaction/concerns/hashable'
22
+ require_relative 'active_interaction/concerns/missable'
23
+ require_relative 'active_interaction/concerns/runnable'
24
+
25
+ require_relative 'active_interaction/grouped_input'
26
+ require_relative 'active_interaction/input'
27
+ require_relative 'active_interaction/array_input'
28
+ require_relative 'active_interaction/hash_input'
29
+ require_relative 'active_interaction/inputs'
30
+
31
+ require_relative 'active_interaction/modules/validation'
32
+
33
+ require_relative 'active_interaction/filter/column'
34
+ require_relative 'active_interaction/filter/error'
35
+ require_relative 'active_interaction/filter'
36
+ require_relative 'active_interaction/filters/interface_filter'
37
+ require_relative 'active_interaction/filters/abstract_date_time_filter'
38
+ require_relative 'active_interaction/filters/abstract_numeric_filter'
39
+ require_relative 'active_interaction/filters/array_filter'
40
+ require_relative 'active_interaction/filters/boolean_filter'
41
+ require_relative 'active_interaction/filters/date_filter'
42
+ require_relative 'active_interaction/filters/date_time_filter'
43
+ require_relative 'active_interaction/filters/decimal_filter'
44
+ require_relative 'active_interaction/filters/file_filter'
45
+ require_relative 'active_interaction/filters/float_filter'
46
+ require_relative 'active_interaction/filters/hash_filter'
47
+ require_relative 'active_interaction/filters/integer_filter'
48
+ require_relative 'active_interaction/filters/object_filter'
49
+ require_relative 'active_interaction/filters/record_filter'
50
+ require_relative 'active_interaction/filters/string_filter'
51
+ require_relative 'active_interaction/filters/symbol_filter'
52
+ require_relative 'active_interaction/filters/time_filter'
53
+
54
+ require_relative 'active_interaction/base'
48
55
 
49
56
  I18n.load_path.unshift(
50
57
  *Dir.glob(