active_interaction 2.1.5 → 2.2.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +26 -3
  4. data/lib/active_interaction.rb +1 -2
  5. data/lib/active_interaction/backports.rb +1 -0
  6. data/lib/active_interaction/base.rb +3 -2
  7. data/lib/active_interaction/concerns/active_modelable.rb +1 -0
  8. data/lib/active_interaction/concerns/active_recordable.rb +1 -0
  9. data/lib/active_interaction/concerns/hashable.rb +1 -0
  10. data/lib/active_interaction/concerns/missable.rb +1 -0
  11. data/lib/active_interaction/concerns/runnable.rb +1 -0
  12. data/lib/active_interaction/errors.rb +1 -0
  13. data/lib/active_interaction/filter.rb +16 -9
  14. data/lib/active_interaction/filter_column.rb +1 -0
  15. data/lib/active_interaction/filters/abstract_date_time_filter.rb +6 -5
  16. data/lib/active_interaction/filters/abstract_filter.rb +1 -0
  17. data/lib/active_interaction/filters/abstract_numeric_filter.rb +5 -4
  18. data/lib/active_interaction/filters/array_filter.rb +3 -2
  19. data/lib/active_interaction/filters/boolean_filter.rb +2 -1
  20. data/lib/active_interaction/filters/date_filter.rb +1 -0
  21. data/lib/active_interaction/filters/date_time_filter.rb +1 -0
  22. data/lib/active_interaction/filters/decimal_filter.rb +2 -1
  23. data/lib/active_interaction/filters/file_filter.rb +1 -0
  24. data/lib/active_interaction/filters/float_filter.rb +1 -0
  25. data/lib/active_interaction/filters/hash_filter.rb +6 -5
  26. data/lib/active_interaction/filters/integer_filter.rb +1 -0
  27. data/lib/active_interaction/filters/interface_filter.rb +2 -1
  28. data/lib/active_interaction/filters/object_filter.rb +4 -3
  29. data/lib/active_interaction/filters/string_filter.rb +2 -1
  30. data/lib/active_interaction/filters/symbol_filter.rb +2 -1
  31. data/lib/active_interaction/filters/time_filter.rb +2 -1
  32. data/lib/active_interaction/grouped_input.rb +1 -0
  33. data/lib/active_interaction/modules/input_processor.rb +1 -0
  34. data/lib/active_interaction/modules/validation.rb +4 -2
  35. data/lib/active_interaction/version.rb +2 -1
  36. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +1 -1
  37. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +1 -1
  38. data/spec/active_interaction/filters/array_filter_spec.rb +1 -1
  39. data/spec/active_interaction/filters/boolean_filter_spec.rb +2 -2
  40. data/spec/active_interaction/filters/date_filter_spec.rb +2 -2
  41. data/spec/active_interaction/filters/date_time_filter_spec.rb +2 -2
  42. data/spec/active_interaction/filters/decimal_filter_spec.rb +1 -1
  43. data/spec/active_interaction/filters/file_filter_spec.rb +1 -1
  44. data/spec/active_interaction/filters/float_filter_spec.rb +1 -1
  45. data/spec/active_interaction/filters/hash_filter_spec.rb +3 -3
  46. data/spec/active_interaction/filters/integer_filter_spec.rb +1 -1
  47. data/spec/active_interaction/filters/interface_filter_spec.rb +1 -1
  48. data/spec/active_interaction/filters/object_filter_spec.rb +4 -4
  49. data/spec/active_interaction/filters/string_filter_spec.rb +1 -1
  50. data/spec/active_interaction/filters/symbol_filter_spec.rb +1 -1
  51. data/spec/active_interaction/filters/time_filter_spec.rb +2 -2
  52. data/spec/active_interaction/modules/validation_spec.rb +11 -4
  53. data/spec/support/filters.rb +11 -11
  54. data/spec/support/interactions.rb +6 -0
  55. metadata +17 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7a54101dfa80812134a34c6977fa538e23d67c7f
4
- data.tar.gz: 3a3d21348e1f37a649ca23801a1b01f5974c9399
3
+ metadata.gz: 6ab0b6acaa850b033873f57885ab405bd0617fb1
4
+ data.tar.gz: fa8014160f12647a93e6630e740a7caea0b6e866
5
5
  SHA512:
6
- metadata.gz: 04fe6f23d9235893ca47203481f9f4a7709acffebb0d8f24f3769ccfe07dc8b52133e3e82f2f1be039eaf8a4859572536c106d0bc5fffcf96fffb767c3a4226a
7
- data.tar.gz: df1cf833864649ddb7d402a3da8b657987863da264728f755657625d3cda9293c58968509608b2ae6a12831a71d91141d5c638e7650d10050c666407b0c71945
6
+ metadata.gz: 7c3ba3db8d3d3f6886e0badc849f80036d7633bdc2e4cfef8da3fcf07c556167181bd182757f0b0aae8fd9fc8d273b75a3bcf88d320310f5f7bc41ea6f8d0490
7
+ data.tar.gz: 9b0588c2945678a31fbf315bf2b44f2168d5dbfad1e4398e2c07a558f91ae0fa66ac15622a3b4b049ee103b863ed290091963098cccc1c35e74f64a361b8ee22
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # [2.2.0][] (2015-12-18)
2
+
3
+ ## Added
4
+
5
+ - [#336][]: Added frozen string pragma for Ruby 2.3.
6
+
7
+ ## Changed
8
+
9
+ - [#332][]: Changed default lambdas to be evaluated in the interaction's
10
+ binding.
11
+
1
12
  # [2.1.5][] (2015-12-11)
2
13
 
3
14
  ## Added
@@ -482,6 +493,7 @@ For help upgrading to version 2, please read [the announcement post][].
482
493
 
483
494
  - Initial release.
484
495
 
496
+ [2.2.0]: https://github.com/orgsync/active_interaction/compare/v2.1.5...v2.2.0
485
497
  [2.1.5]: https://github.com/orgsync/active_interaction/compare/v2.1.4...v2.1.5
486
498
  [2.1.4]: https://github.com/orgsync/active_interaction/compare/v2.1.3...v2.1.4
487
499
  [2.1.3]: https://github.com/orgsync/active_interaction/compare/v2.1.2...v2.1.3
@@ -631,5 +643,7 @@ For help upgrading to version 2, please read [the announcement post][].
631
643
  [#311]: https://github.com/orgsync/active_interaction/issues/311
632
644
  [#320]: https://github.com/orgsync/active_interaction/issues/320
633
645
  [#330]: https://github.com/orgsync/active_interaction/pull/330
646
+ [#332]: https://github.com/orgsync/active_interaction/pull/332
647
+ [#336]: https://github.com/orgsync/active_interaction/pull/336
634
648
 
635
649
  [the announcement post]: http://devblog.orgsync.com/2015/05/06/announcing-active-interaction-2/
data/README.md CHANGED
@@ -52,6 +52,7 @@ Read more on [the project page][] or check out [the full documentation][].
52
52
  - [Advanced usage](#advanced-usage)
53
53
  - [Callbacks](#callbacks)
54
54
  - [Composition](#composition)
55
+ - [Defaults](#defaults)
55
56
  - [Descriptions](#descriptions)
56
57
  - [Errors](#errors)
57
58
  - [Forms](#forms)
@@ -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', '~> 2.1'
70
+ gem 'active_interaction', '~> 2.2'
70
71
  ```
71
72
 
72
73
  Or install it manually:
73
74
 
74
75
  ``` sh
75
- $ gem install active_interaction --version '~> 2.1'
76
+ $ gem install active_interaction --version '~> 2.2'
76
77
  ```
77
78
 
78
79
  This project uses [Semantic Versioning][]. Check out [the change log][] for a
@@ -980,6 +981,28 @@ class AddAndDouble < ActiveInteraction::Base
980
981
  end
981
982
  ```
982
983
 
984
+ ### Defaults
985
+
986
+ The default value for an input can take on many different forms. Setting the
987
+ default to `nil` makes the input optional. Setting it to some value makes that
988
+ the default value for that input. Setting it to a lambda will lazily set the
989
+ default value for that input. That means the value will be computed when the
990
+ interaction is run, as opposed to when it is defined.
991
+
992
+ Lambda defaults are evaluated in the context of the interaction, so you can use
993
+ the values of other inputs in them.
994
+
995
+ ``` rb
996
+ # This input is optional.
997
+ time :a, default: nil
998
+ # This input defaults to `Time.at(123)`.
999
+ time :b, default: Time.at(123)
1000
+ # This input lazily defaults to `Time.now`.
1001
+ time :c, default: -> { Time.now }
1002
+ # This input defaults to the value of `c` plus 10 seconds.
1003
+ time :d, default: -> { c + 10 }
1004
+ ```
1005
+
983
1006
  ### Descriptions
984
1007
 
985
1008
  Use the `desc` option to provide human-readable descriptions of filters. You
@@ -1192,7 +1215,7 @@ class UpdateUser < ActiveInteraction::Base
1192
1215
 
1193
1216
  def execute
1194
1217
  user.birthday = birthday if given?(:birthday)
1195
- errors.merge!(user) unless user.save
1218
+ errors.merge!(user.errors) unless user.save
1196
1219
  user
1197
1220
  end
1198
1221
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'active_model'
4
5
 
@@ -8,8 +9,6 @@ require 'active_model'
8
9
  # @author Taylor Fausak <taylor@fausak.me>
9
10
  #
10
11
  # @since 1.0.0
11
- #
12
- # @version 2.1.5
13
12
  module ActiveInteraction
14
13
  end
15
14
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'active_support/core_ext'
4
5
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'active_support/core_ext/hash/indifferent_access'
4
5
  require 'set'
@@ -251,7 +252,7 @@ module ActiveInteraction
251
252
  def populate_filters(inputs)
252
253
  self.class.filters.each do |name, filter|
253
254
  begin
254
- public_send("#{name}=", filter.clean(inputs[name]))
255
+ public_send("#{name}=", filter.clean(inputs[name], self))
255
256
  rescue InvalidValueError, MissingValueError, NoDefaultError
256
257
  # #type_check will add errors if appropriate.
257
258
  end
@@ -260,7 +261,7 @@ module ActiveInteraction
260
261
 
261
262
  def type_check
262
263
  run_callbacks(:type_check) do
263
- Validation.validate(self.class.filters, inputs).each do |error|
264
+ Validation.validate(self, self.class.filters, inputs).each do |error|
264
265
  errors.add(*error)
265
266
  end
266
267
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # Implement the minimal ActiveModel interface.
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # Implement the minimal ActiveRecord interface.
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # Allow `hash` to be overridden when given arguments and/or a block.
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # Handle common `method_missing` functionality.
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # @abstract Include and override {#execute} to implement a custom Runnable
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  #
4
5
  module ActiveInteraction
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'active_support/inflector'
4
5
 
@@ -90,15 +91,16 @@ module ActiveInteraction
90
91
  # # => ActiveInteraction::InvalidDefaultError: example: 0
91
92
  #
92
93
  # @param value [Object]
94
+ # @param context [Base, nil]
93
95
  #
94
96
  # @return [Object]
95
97
  #
96
98
  # @raise (see #cast)
97
99
  # @raise (see #default)
98
- def clean(value)
99
- value = cast(value)
100
+ def clean(value, context)
101
+ value = cast(value, context)
100
102
  if value.nil?
101
- default
103
+ default(context)
102
104
  else
103
105
  value
104
106
  end
@@ -116,17 +118,19 @@ module ActiveInteraction
116
118
  # ActiveInteraction::Filter.new(:example, default: 0).default
117
119
  # # => ActiveInteraction::InvalidDefaultError: example: 0
118
120
  #
121
+ # @param context [Base, nil]
122
+ #
119
123
  # @return (see #raw_default)
120
124
  #
121
125
  # @raise [NoDefaultError] If the default is missing.
122
126
  # @raise [InvalidDefaultError] If the default is invalid.
123
- def default
127
+ def default(context = nil)
124
128
  fail NoDefaultError, name unless default?
125
129
 
126
- value = raw_default
130
+ value = raw_default(context)
127
131
  fail InvalidValueError if value.is_a?(GroupedInput)
128
132
 
129
- cast(value)
133
+ cast(value, context)
130
134
  rescue InvalidNestedValueError => error
131
135
  raise InvalidDefaultError, "#{name}: #{value.inspect} (#{error})"
132
136
  rescue InvalidValueError, MissingValueError
@@ -159,6 +163,7 @@ module ActiveInteraction
159
163
  end
160
164
 
161
165
  # @param value [Object]
166
+ # @param _interaction [Base, nil]
162
167
  #
163
168
  # @return [Object]
164
169
  #
@@ -167,7 +172,7 @@ module ActiveInteraction
167
172
  # @raise [InvalidValueError] If the value is invalid.
168
173
  #
169
174
  # @private
170
- def cast(value)
175
+ def cast(value, _interaction)
171
176
  case value
172
177
  when NilClass
173
178
  fail MissingValueError, name unless default?
@@ -205,12 +210,14 @@ module ActiveInteraction
205
210
  "(Object doesn't support #inspect)"
206
211
  end
207
212
 
213
+ # @param context [Base, nil]
214
+ #
208
215
  # @return [Object]
209
- def raw_default
216
+ def raw_default(context)
210
217
  value = options.fetch(:default)
211
218
 
212
219
  if value.is_a?(Proc)
213
- value.call
220
+ context.instance_exec(&value)
214
221
  else
215
222
  value
216
223
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # A minimal implementation of an `ActiveRecord::ConnectionAdapters::Column`.
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # @abstract
@@ -11,12 +12,12 @@ module ActiveInteraction
11
12
  alias_method :_cast, :cast
12
13
  private :_cast
13
14
 
14
- def cast(value)
15
+ def cast(value, context)
15
16
  case value
16
17
  when String
17
- convert(value)
18
+ convert(value, context)
18
19
  when GroupedInput
19
- convert(stringify(value))
20
+ convert(stringify(value), context)
20
21
  when *klasses
21
22
  value
22
23
  else
@@ -30,7 +31,7 @@ module ActiveInteraction
30
31
 
31
32
  private
32
33
 
33
- def convert(value)
34
+ def convert(value, context)
34
35
  if format?
35
36
  klass.strptime(value, format)
36
37
  else
@@ -38,7 +39,7 @@ module ActiveInteraction
38
39
  (fail ArgumentError, "no time information in #{value.inspect}")
39
40
  end
40
41
  rescue ArgumentError
41
- _cast(value)
42
+ _cast(value, context)
42
43
  end
43
44
 
44
45
  # @return [String]
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # @abstract
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # @abstract
@@ -10,12 +11,12 @@ module ActiveInteraction
10
11
  alias_method :_cast, :cast
11
12
  private :_cast
12
13
 
13
- def cast(value)
14
+ def cast(value, context)
14
15
  case value
15
16
  when klass
16
17
  value
17
18
  when Numeric, String
18
- convert(value)
19
+ convert(value, context)
19
20
  else
20
21
  super
21
22
  end
@@ -27,10 +28,10 @@ module ActiveInteraction
27
28
 
28
29
  private
29
30
 
30
- def convert(value)
31
+ def convert(value, context)
31
32
  Kernel.public_send(klass.name, value)
32
33
  rescue ArgumentError
33
- _cast(value)
34
+ _cast(value, context)
34
35
  end
35
36
  end
36
37
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -27,13 +28,13 @@ module ActiveInteraction
27
28
 
28
29
  register :array
29
30
 
30
- def cast(value)
31
+ def cast(value, context)
31
32
  case value
32
33
  when *classes
33
34
  return value if filters.empty?
34
35
 
35
36
  filter = filters.values.first
36
- value.map { |e| filter.clean(e) }
37
+ value.map { |e| filter.clean(e, context) }
37
38
  else
38
39
  super
39
40
  end
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -18,7 +19,7 @@ module ActiveInteraction
18
19
  class BooleanFilter < Filter
19
20
  register :boolean
20
21
 
21
- def cast(value)
22
+ def cast(value, _interaction)
22
23
  case value
23
24
  when FalseClass, '0', /\Afalse\z/i
24
25
  false
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bigdecimal'
4
5
 
@@ -21,7 +22,7 @@ module ActiveInteraction
21
22
  class DecimalFilter < AbstractNumericFilter
22
23
  register :decimal
23
24
 
24
- def cast(value)
25
+ def cast(value, _interaction)
25
26
  case value
26
27
  when Numeric
27
28
  BigDecimal.new(value, digits)
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -25,14 +26,14 @@ module ActiveInteraction
25
26
 
26
27
  register :hash
27
28
 
28
- def cast(value)
29
+ def cast(value, context)
29
30
  case value
30
31
  when Hash
31
32
  value = value.with_indifferent_access
32
33
  initial = strip? ? ActiveSupport::HashWithIndifferentAccess.new : value
33
34
 
34
35
  filters.each_with_object(initial) do |(name, filter), h|
35
- clean_value(h, name.to_s, filter, value)
36
+ clean_value(h, name.to_s, filter, value, context)
36
37
  end
37
38
  else
38
39
  super
@@ -51,13 +52,13 @@ module ActiveInteraction
51
52
 
52
53
  private
53
54
 
54
- def clean_value(h, name, filter, value)
55
- h[name] = filter.clean(value[name])
55
+ def clean_value(h, name, filter, value, context)
56
+ h[name] = filter.clean(value[name], context)
56
57
  rescue InvalidValueError, MissingValueError
57
58
  raise InvalidNestedValueError.new(name, value[name])
58
59
  end
59
60
 
60
- def raw_default
61
+ def raw_default(*)
61
62
  value = super
62
63
 
63
64
  if value.is_a?(Hash) && !value.empty?
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -21,7 +22,7 @@ module ActiveInteraction
21
22
  class InterfaceFilter < Filter
22
23
  register :interface
23
24
 
24
- def cast(value)
25
+ def cast(value, _interaction)
25
26
  matches?(value) ? value : super
26
27
  end
27
28
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -20,16 +21,16 @@ module ActiveInteraction
20
21
  class ObjectFilter < Filter
21
22
  register :object
22
23
 
23
- def cast(value, reconstantize = true)
24
+ def cast(value, context, reconstantize = true)
24
25
  @klass ||= klass
25
26
 
26
27
  if matches?(value)
27
28
  value
28
29
  else
29
- return super(value) unless reconstantize
30
+ return super(value, context) unless reconstantize
30
31
 
31
32
  @klass = klass
32
- cast(value, false)
33
+ cast(value, context, false)
33
34
  end
34
35
  end
35
36
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -20,7 +21,7 @@ module ActiveInteraction
20
21
  class StringFilter < Filter
21
22
  register :string
22
23
 
23
- def cast(value)
24
+ def cast(value, _interaction)
24
25
  case value
25
26
  when String
26
27
  strip? ? value.strip : value
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -16,7 +17,7 @@ module ActiveInteraction
16
17
  class SymbolFilter < Filter
17
18
  register :symbol
18
19
 
19
- def cast(value)
20
+ def cast(value, _interaction)
20
21
  case value
21
22
  when Symbol
22
23
  value
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  class Base
@@ -34,7 +35,7 @@ module ActiveInteraction
34
35
  super
35
36
  end
36
37
 
37
- def cast(value)
38
+ def cast(value, _interaction)
38
39
  case value
39
40
  when Numeric
40
41
  klass.at(value)
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'ostruct'
4
5
 
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # Groups inputs ending in "(*N*i)" into {GroupedInput}.
@@ -1,4 +1,5 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  module ActiveInteraction
4
5
  # Validates inputs using filters.
@@ -6,12 +7,13 @@ module ActiveInteraction
6
7
  # @private
7
8
  module Validation
8
9
  class << self
10
+ # @param context [Base]
9
11
  # @param filters [Hash{Symbol => Filter}]
10
12
  # @param inputs [Hash{Symbol => Object}]
11
- def validate(filters, inputs)
13
+ def validate(context, filters, inputs)
12
14
  filters.each_with_object([]) do |(name, filter), errors|
13
15
  begin
14
- filter.cast(inputs[name])
16
+ filter.cast(inputs[name], context)
15
17
  rescue InvalidNestedValueError,
16
18
  InvalidValueError,
17
19
  MissingValueError => e
@@ -1,9 +1,10 @@
1
1
  # coding: utf-8
2
+ # frozen_string_literal: true
2
3
 
3
4
  #
4
5
  module ActiveInteraction
5
6
  # The version number.
6
7
  #
7
8
  # @return [Gem::Version]
8
- VERSION = Gem::Version.new('2.1.5')
9
+ VERSION = Gem::Version.new('2.2.0')
9
10
  end
@@ -9,7 +9,7 @@ describe ActiveInteraction::AbstractDateTimeFilter, :filter do
9
9
  let(:value) { nil }
10
10
 
11
11
  it 'raises an error' do
12
- expect { filter.cast(value) }.to raise_error NameError
12
+ expect { filter.cast(value, nil) }.to raise_error NameError
13
13
  end
14
14
  end
15
15
  end
@@ -9,7 +9,7 @@ describe ActiveInteraction::AbstractNumericFilter, :filter do
9
9
  let(:value) { nil }
10
10
 
11
11
  it 'raises an error' do
12
- expect { filter.cast(value) }.to raise_error NameError
12
+ expect { filter.cast(value, nil) }.to raise_error NameError
13
13
  end
14
14
  end
15
15
  end
@@ -36,7 +36,7 @@ describe ActiveInteraction::ArrayFilter, :filter do
36
36
  end
37
37
 
38
38
  describe '#cast' do
39
- let(:result) { filter.cast(value) }
39
+ let(:result) { filter.cast(value, nil) }
40
40
 
41
41
  context 'with an Array' do
42
42
  let(:value) { [] }
@@ -10,7 +10,7 @@ describe ActiveInteraction::BooleanFilter, :filter do
10
10
  context 'falsey' do
11
11
  [false, '0', 'false', 'FALSE'].each do |value|
12
12
  it "returns false for #{value.inspect}" do
13
- expect(filter.cast(value)).to be_falsey
13
+ expect(filter.cast(value, nil)).to be_falsey
14
14
  end
15
15
  end
16
16
  end
@@ -18,7 +18,7 @@ describe ActiveInteraction::BooleanFilter, :filter do
18
18
  context 'truthy' do
19
19
  [true, '1', 'true', 'TRUE'].each do |value|
20
20
  it "returns true for #{value.inspect}" do
21
- expect(filter.cast(value)).to be_truthy
21
+ expect(filter.cast(value, nil)).to be_truthy
22
22
  end
23
23
  end
24
24
  end
@@ -15,7 +15,7 @@ describe ActiveInteraction::DateFilter, :filter do
15
15
  end
16
16
 
17
17
  describe '#cast' do
18
- let(:result) { filter.cast(value) }
18
+ let(:result) { filter.cast(value, nil) }
19
19
 
20
20
  context 'with a Date' do
21
21
  let(:value) { Date.new }
@@ -127,7 +127,7 @@ describe ActiveInteraction::DateFilter, :filter do
127
127
 
128
128
  it 'raises an error' do
129
129
  expect do
130
- filter.default
130
+ filter.default(nil)
131
131
  end.to raise_error ActiveInteraction::InvalidDefaultError
132
132
  end
133
133
  end
@@ -15,7 +15,7 @@ describe ActiveInteraction::DateTimeFilter, :filter do
15
15
  end
16
16
 
17
17
  describe '#cast' do
18
- let(:result) { filter.cast(value) }
18
+ let(:result) { filter.cast(value, nil) }
19
19
 
20
20
  context 'with a Datetime' do
21
21
  let(:value) { DateTime.new }
@@ -138,7 +138,7 @@ describe ActiveInteraction::DateTimeFilter, :filter do
138
138
 
139
139
  it 'raises an error' do
140
140
  expect do
141
- filter.default
141
+ filter.default(nil)
142
142
  end.to raise_error ActiveInteraction::InvalidDefaultError
143
143
  end
144
144
  end
@@ -15,7 +15,7 @@ describe ActiveInteraction::DecimalFilter, :filter do
15
15
  end
16
16
 
17
17
  describe '#cast' do
18
- let(:result) { filter.cast(value) }
18
+ let(:result) { filter.cast(value, nil) }
19
19
 
20
20
  context 'with a Float' do
21
21
  let(:value) { rand }
@@ -7,7 +7,7 @@ describe ActiveInteraction::FileFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
- let(:result) { filter.cast(value) }
10
+ let(:result) { filter.cast(value, nil) }
11
11
 
12
12
  context 'with a File' do
13
13
  let(:value) { File.new(__FILE__) }
@@ -7,7 +7,7 @@ describe ActiveInteraction::FloatFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
- let(:result) { filter.cast(value) }
10
+ let(:result) { filter.cast(value, nil) }
11
11
 
12
12
  context 'with a Float' do
13
13
  let(:value) { rand }
@@ -25,7 +25,7 @@ describe ActiveInteraction::HashFilter, :filter do
25
25
  end
26
26
 
27
27
  describe '#cast' do
28
- let(:result) { filter.cast(value) }
28
+ let(:result) { filter.cast(value, nil) }
29
29
 
30
30
  context 'with a Hash' do
31
31
  let(:value) { {} }
@@ -94,7 +94,7 @@ describe ActiveInteraction::HashFilter, :filter do
94
94
  end
95
95
 
96
96
  it 'returns the Hash' do
97
- expect(filter.default).to eql options[:default]
97
+ expect(filter.default(nil)).to eql options[:default]
98
98
  end
99
99
  end
100
100
 
@@ -105,7 +105,7 @@ describe ActiveInteraction::HashFilter, :filter do
105
105
 
106
106
  it 'raises an error' do
107
107
  expect do
108
- filter.default
108
+ filter.default(nil)
109
109
  end.to raise_error ActiveInteraction::InvalidDefaultError
110
110
  end
111
111
  end
@@ -7,7 +7,7 @@ describe ActiveInteraction::IntegerFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
- let(:result) { filter.cast(value) }
10
+ let(:result) { filter.cast(value, nil) }
11
11
 
12
12
  context 'with an Integer' do
13
13
  let(:value) { rand(1 << 16) }
@@ -11,7 +11,7 @@ describe ActiveInteraction::InterfaceFilter, :filter do
11
11
  before { options[:methods] = [:dump, :load] }
12
12
 
13
13
  describe '#cast' do
14
- let(:result) { filter.cast(value) }
14
+ let(:result) { filter.cast(value, nil) }
15
15
 
16
16
  context 'with a BasicObject' do
17
17
  let(:value) { BasicObject.new }
@@ -15,7 +15,7 @@ describe ActiveInteraction::ObjectFilter, :filter do
15
15
 
16
16
  describe '#cast' do
17
17
  let(:value) { Thing.new }
18
- let(:result) { filter.cast(value) }
18
+ let(:result) { filter.cast(value, nil) }
19
19
 
20
20
  context 'with class as a Class' do
21
21
  it 'returns the instance' do
@@ -29,7 +29,7 @@ describe ActiveInteraction::ObjectFilter, :filter do
29
29
  class Thing; end
30
30
  value = Thing.new
31
31
 
32
- expect(filter.cast(value)).to eql value
32
+ expect(filter.cast(value, nil)).to eql value
33
33
  end
34
34
 
35
35
  it 'handles reconstantizing subclasses' do
@@ -40,7 +40,7 @@ describe ActiveInteraction::ObjectFilter, :filter do
40
40
  class SubThing < Thing; end
41
41
  value = SubThing.new
42
42
 
43
- expect(filter.cast(value)).to eql value
43
+ expect(filter.cast(value, nil)).to eql value
44
44
  end
45
45
 
46
46
  it 'does not overflow the stack' do
@@ -51,7 +51,7 @@ describe ActiveInteraction::ObjectFilter, :filter do
51
51
  end
52
52
 
53
53
  expect do
54
- filter.cast(klass.new)
54
+ filter.cast(klass.new, nil)
55
55
  end.to raise_error ActiveInteraction::InvalidValueError
56
56
  end
57
57
 
@@ -13,7 +13,7 @@ describe ActiveInteraction::StringFilter, :filter do
13
13
  end
14
14
 
15
15
  describe '#cast' do
16
- let(:result) { filter.cast(value) }
16
+ let(:result) { filter.cast(value, nil) }
17
17
 
18
18
  context 'with a String' do
19
19
  let(:value) { SecureRandom.hex }
@@ -7,7 +7,7 @@ describe ActiveInteraction::SymbolFilter, :filter do
7
7
  it_behaves_like 'a filter'
8
8
 
9
9
  describe '#cast' do
10
- let(:result) { filter.cast(value) }
10
+ let(:result) { filter.cast(value, nil) }
11
11
 
12
12
  context 'with a Symbol' do
13
13
  let(:value) { SecureRandom.hex.to_sym }
@@ -37,7 +37,7 @@ describe ActiveInteraction::TimeFilter, :filter do
37
37
  end
38
38
 
39
39
  describe '#cast' do
40
- let(:result) { filter.cast(value) }
40
+ let(:result) { filter.cast(value, nil) }
41
41
 
42
42
  context 'with a Time' do
43
43
  let(:value) { Time.new }
@@ -160,7 +160,7 @@ describe ActiveInteraction::TimeFilter, :filter do
160
160
 
161
161
  it 'raises an error' do
162
162
  expect do
163
- filter.default
163
+ filter.default(nil)
164
164
  end.to raise_error ActiveInteraction::InvalidDefaultError
165
165
  end
166
166
  end
@@ -3,14 +3,21 @@
3
3
  require 'spec_helper'
4
4
 
5
5
  describe ActiveInteraction::Validation do
6
- describe '.validate(filters, inputs)' do
6
+ describe '.validate(context, filters, inputs)' do
7
7
  let(:inputs) { {} }
8
8
  let(:filter) { ActiveInteraction::Filter.new(:name, {}) }
9
- let(:filters) { { filter.name => filter } }
10
- let(:result) { described_class.validate(filters, inputs) }
9
+ let(:interaction) do
10
+ name = filter.name
11
+ klass = Class.new(ActiveInteraction::Base) { attr_writer(name) }
12
+ klass.filters[name] = filter
13
+ klass.new
14
+ end
15
+ let(:result) do
16
+ described_class.validate(interaction, interaction.class.filters, inputs)
17
+ end
11
18
 
12
19
  context 'no filters are given' do
13
- let(:filters) { {} }
20
+ let(:interaction) { Class.new(ActiveInteraction::Base).new }
14
21
 
15
22
  it 'returns no errors' do
16
23
  expect(result).to eql []
@@ -54,7 +54,7 @@ shared_examples_for 'a filter' do
54
54
  include_context 'optional'
55
55
 
56
56
  it 'returns nil' do
57
- expect(filter.cast(value)).to be_nil
57
+ expect(filter.cast(value, nil)).to be_nil
58
58
  end
59
59
  end
60
60
 
@@ -63,7 +63,7 @@ shared_examples_for 'a filter' do
63
63
 
64
64
  it 'raises an error' do
65
65
  expect do
66
- filter.cast(value)
66
+ filter.cast(value, nil)
67
67
  end.to raise_error ActiveInteraction::MissingValueError
68
68
  end
69
69
 
@@ -72,7 +72,7 @@ shared_examples_for 'a filter' do
72
72
 
73
73
  it 'raises an error' do
74
74
  expect do
75
- filter.cast(value)
75
+ filter.cast(value, nil)
76
76
  end.to raise_error ActiveInteraction::InvalidValueError
77
77
  end
78
78
  end
@@ -86,7 +86,7 @@ shared_examples_for 'a filter' do
86
86
  include_context 'optional'
87
87
 
88
88
  it 'returns the default' do
89
- expect(filter.clean(value)).to eql options[:default]
89
+ expect(filter.clean(value, nil)).to eql options[:default]
90
90
  end
91
91
  end
92
92
 
@@ -95,7 +95,7 @@ shared_examples_for 'a filter' do
95
95
 
96
96
  it 'raises an error' do
97
97
  expect do
98
- filter.clean(value)
98
+ filter.clean(value, nil)
99
99
  end.to raise_error ActiveInteraction::MissingValueError
100
100
  end
101
101
 
@@ -104,7 +104,7 @@ shared_examples_for 'a filter' do
104
104
 
105
105
  it 'raises an error' do
106
106
  expect do
107
- filter.clean(value)
107
+ filter.clean(value, nil)
108
108
  end.to raise_error ActiveInteraction::InvalidValueError
109
109
  end
110
110
  end
@@ -117,7 +117,7 @@ shared_examples_for 'a filter' do
117
117
 
118
118
  it 'raises an error' do
119
119
  expect do
120
- filter.clean(value)
120
+ filter.clean(value, nil)
121
121
  end.to raise_error ActiveInteraction::InvalidDefaultError
122
122
  end
123
123
  end
@@ -128,7 +128,7 @@ shared_examples_for 'a filter' do
128
128
  include_context 'optional'
129
129
 
130
130
  it 'returns the default' do
131
- expect(filter.default).to eql options[:default]
131
+ expect(filter.default(nil)).to eql options[:default]
132
132
  end
133
133
  end
134
134
 
@@ -137,7 +137,7 @@ shared_examples_for 'a filter' do
137
137
 
138
138
  it 'raises an error' do
139
139
  expect do
140
- filter.default
140
+ filter.default(nil)
141
141
  end.to raise_error ActiveInteraction::NoDefaultError
142
142
  end
143
143
  end
@@ -149,7 +149,7 @@ shared_examples_for 'a filter' do
149
149
 
150
150
  it 'raises an error' do
151
151
  expect do
152
- filter.default
152
+ filter.default(nil)
153
153
  end.to raise_error ActiveInteraction::InvalidDefaultError
154
154
  end
155
155
  end
@@ -163,7 +163,7 @@ shared_examples_for 'a filter' do
163
163
  end
164
164
 
165
165
  it 'returns the default' do
166
- expect(filter.default).to eql options[:default].call
166
+ expect(filter.default(nil)).to eql options[:default].call
167
167
  end
168
168
  end
169
169
  end
@@ -27,6 +27,8 @@ shared_examples_for 'an interaction' do |type, generator, filter_options = {}|
27
27
  filter_options.merge(default: generator.call))
28
28
  public_send(type, :defaults_1, :defaults_2,
29
29
  filter_options.merge(default: generator.call))
30
+ public_send(type, :defaults_3,
31
+ filter_options.merge(default: -> { required }))
30
32
  end
31
33
  end
32
34
 
@@ -83,6 +85,10 @@ shared_examples_for 'an interaction' do |type, generator, filter_options = {}|
83
85
  expect(result[:defaults_2]).to_not be_nil
84
86
  end
85
87
 
88
+ it 'evaluates :defaults_3 in the interaction binding' do
89
+ expect(result[:defaults_3]).to eql result[:required]
90
+ end
91
+
86
92
  context 'with inputs[:optional]' do
87
93
  let(:optional) { generator.call }
88
94
 
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: 2.1.5
4
+ version: 2.2.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: 2015-12-12 00:00:00.000000000 Z
12
+ date: 2015-12-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -51,6 +51,20 @@ dependencies:
51
51
  - - "<"
52
52
  - !ruby/object:Gem::Version
53
53
  version: '5'
54
+ - !ruby/object:Gem::Dependency
55
+ name: benchmark-ips
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.3'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.3'
54
68
  - !ruby/object:Gem::Dependency
55
69
  name: bundler
56
70
  requirement: !ruby/object:Gem::Requirement
@@ -292,7 +306,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
292
306
  version: '0'
293
307
  requirements: []
294
308
  rubyforge_project:
295
- rubygems_version: 2.4.5.1
309
+ rubygems_version: 2.4.5
296
310
  signing_key:
297
311
  specification_version: 4
298
312
  summary: Manage application specific business logic.