active_interaction 3.8.3 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +157 -0
  3. data/README.md +93 -107
  4. data/lib/active_interaction.rb +1 -7
  5. data/lib/active_interaction/base.rb +23 -26
  6. data/lib/active_interaction/concerns/active_modelable.rb +1 -3
  7. data/lib/active_interaction/concerns/active_recordable.rb +1 -6
  8. data/lib/active_interaction/concerns/hashable.rb +0 -1
  9. data/lib/active_interaction/concerns/missable.rb +0 -1
  10. data/lib/active_interaction/concerns/runnable.rb +6 -12
  11. data/lib/active_interaction/errors.rb +3 -6
  12. data/lib/active_interaction/filter.rb +51 -37
  13. data/lib/active_interaction/filter_column.rb +0 -3
  14. data/lib/active_interaction/filters/abstract_date_time_filter.rb +34 -36
  15. data/lib/active_interaction/filters/abstract_numeric_filter.rb +27 -17
  16. data/lib/active_interaction/filters/array_filter.rb +57 -36
  17. data/lib/active_interaction/filters/boolean_filter.rb +26 -12
  18. data/lib/active_interaction/filters/date_filter.rb +1 -2
  19. data/lib/active_interaction/filters/date_time_filter.rb +1 -2
  20. data/lib/active_interaction/filters/decimal_filter.rb +10 -28
  21. data/lib/active_interaction/filters/file_filter.rb +6 -5
  22. data/lib/active_interaction/filters/float_filter.rb +1 -2
  23. data/lib/active_interaction/filters/hash_filter.rb +37 -27
  24. data/lib/active_interaction/filters/integer_filter.rb +7 -8
  25. data/lib/active_interaction/filters/interface_filter.rb +48 -14
  26. data/lib/active_interaction/filters/object_filter.rb +23 -50
  27. data/lib/active_interaction/filters/record_filter.rb +10 -35
  28. data/lib/active_interaction/filters/string_filter.rb +21 -12
  29. data/lib/active_interaction/filters/symbol_filter.rb +13 -7
  30. data/lib/active_interaction/filters/time_filter.rb +19 -22
  31. data/lib/active_interaction/grouped_input.rb +0 -3
  32. data/lib/active_interaction/inputs.rb +89 -0
  33. data/lib/active_interaction/modules/input_processor.rb +1 -4
  34. data/lib/active_interaction/modules/validation.rb +9 -12
  35. data/lib/active_interaction/version.rb +1 -3
  36. data/spec/active_interaction/base_spec.rb +13 -41
  37. data/spec/active_interaction/concerns/active_modelable_spec.rb +0 -2
  38. data/spec/active_interaction/concerns/active_recordable_spec.rb +0 -2
  39. data/spec/active_interaction/concerns/hashable_spec.rb +1 -3
  40. data/spec/active_interaction/concerns/missable_spec.rb +0 -2
  41. data/spec/active_interaction/concerns/runnable_spec.rb +9 -13
  42. data/spec/active_interaction/errors_spec.rb +4 -25
  43. data/spec/active_interaction/filter_column_spec.rb +0 -2
  44. data/spec/active_interaction/filter_spec.rb +0 -2
  45. data/spec/active_interaction/filters/abstract_date_time_filter_spec.rb +1 -3
  46. data/spec/active_interaction/filters/abstract_numeric_filter_spec.rb +1 -3
  47. data/spec/active_interaction/filters/array_filter_spec.rb +41 -15
  48. data/spec/active_interaction/filters/boolean_filter_spec.rb +58 -4
  49. data/spec/active_interaction/filters/date_filter_spec.rb +43 -3
  50. data/spec/active_interaction/filters/date_time_filter_spec.rb +43 -3
  51. data/spec/active_interaction/filters/decimal_filter_spec.rb +57 -3
  52. data/spec/active_interaction/filters/file_filter_spec.rb +1 -3
  53. data/spec/active_interaction/filters/float_filter_spec.rb +60 -4
  54. data/spec/active_interaction/filters/hash_filter_spec.rb +19 -9
  55. data/spec/active_interaction/filters/integer_filter_spec.rb +49 -7
  56. data/spec/active_interaction/filters/interface_filter_spec.rb +397 -24
  57. data/spec/active_interaction/filters/object_filter_spec.rb +23 -59
  58. data/spec/active_interaction/filters/record_filter_spec.rb +23 -49
  59. data/spec/active_interaction/filters/string_filter_spec.rb +15 -3
  60. data/spec/active_interaction/filters/symbol_filter_spec.rb +15 -3
  61. data/spec/active_interaction/filters/time_filter_spec.rb +65 -3
  62. data/spec/active_interaction/grouped_input_spec.rb +0 -2
  63. data/spec/active_interaction/i18n_spec.rb +3 -7
  64. data/spec/active_interaction/{modules/input_processor_spec.rb → inputs_spec.rb} +3 -5
  65. data/spec/active_interaction/integration/array_interaction_spec.rb +18 -22
  66. data/spec/active_interaction/integration/boolean_interaction_spec.rb +0 -2
  67. data/spec/active_interaction/integration/date_interaction_spec.rb +0 -2
  68. data/spec/active_interaction/integration/date_time_interaction_spec.rb +0 -2
  69. data/spec/active_interaction/integration/file_interaction_spec.rb +0 -2
  70. data/spec/active_interaction/integration/float_interaction_spec.rb +0 -2
  71. data/spec/active_interaction/integration/hash_interaction_spec.rb +0 -2
  72. data/spec/active_interaction/integration/integer_interaction_spec.rb +0 -2
  73. data/spec/active_interaction/integration/interface_interaction_spec.rb +1 -3
  74. data/spec/active_interaction/integration/object_interaction_spec.rb +0 -2
  75. data/spec/active_interaction/integration/string_interaction_spec.rb +0 -2
  76. data/spec/active_interaction/integration/symbol_interaction_spec.rb +0 -2
  77. data/spec/active_interaction/integration/time_interaction_spec.rb +14 -18
  78. data/spec/active_interaction/modules/validation_spec.rb +1 -3
  79. data/spec/spec_helper.rb +2 -6
  80. data/spec/support/concerns.rb +0 -2
  81. data/spec/support/filters.rb +13 -9
  82. data/spec/support/interactions.rb +22 -14
  83. metadata +77 -52
  84. data/lib/active_interaction/backports.rb +0 -59
  85. data/lib/active_interaction/filters/abstract_filter.rb +0 -19
  86. data/spec/active_interaction/filters/abstract_filter_spec.rb +0 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 883e2c22dbe4db00730bd2d917d7812e6f79898f41cfdcde16bc685b1ae1de29
4
- data.tar.gz: 4c1af0be75d96c6801b288b450d260580b3d12f330ebeb69b1f6b20d88da5241
3
+ metadata.gz: acc5f59cdd588429a58556cea7b70aa0c43a6a13c523a682cac266cfc7ab76a1
4
+ data.tar.gz: 9a58db1735b436ae91a70baf9c2eab9ef4851a20a9e51c05c6f243af6e3c282b
5
5
  SHA512:
6
- metadata.gz: d2426683e3249c63760a59a25c0a7e8d21780bedf31218676ffca3d75903db0f4b73c18d80b78bbc568997ca67106490bac774bf43f68dacbe5ba00541e08e78
7
- data.tar.gz: 412ae553643fd1449c9063058f5d4b8f39ea0bb97f4f166db73bee7ae6bf70a5f01b4ca8ee08a867417b8f7d83d57845d5168383c5ac69d2a931df7490527056
6
+ metadata.gz: c78b1f82d8593a238a2076f7351146e51079d163d963cc830d9e086bbc82bd791fbc95527d4fc829e3c38039bb77ce06fefe82520f5b6f2148a64384a8e3a339
7
+ data.tar.gz: 362a8b86512c8ef05d9582a377000e06e2b8b0855c112458020911fa77477c3c98cd10555e81d259cfc767f79c1eb8b03e9ec12124cfca38c552208006e1a70a
@@ -1,3 +1,157 @@
1
+ # [4.0.0][] (2021-01-10)
2
+
3
+ ## Changed
4
+
5
+ - drop support for Ruby < 2.5, added support for Ruby 3.0
6
+ - drop support for Rails < 5.0, added support for Rails 6.1
7
+ - [#398][] - Predicate methods have been removed.
8
+ ([how to upgrade](#predicate-methods))
9
+ - [#412][] - Filters will now treat blank string values as `nil`
10
+ (except `string` and `symbol`). ([how to upgrade](#blank-values-treated-as-nil-for-filters))
11
+ - [#392][] - Integer parsing now defaults the base to 10.
12
+ ([how to upgrade](#integer-parsing-base-now-10))
13
+ - The `inputs` method now returns an `ActiveInteraction::Input` instead of a
14
+ hash. The `ActiveInteraction::Input` class still responds to all hash methods.
15
+ - The `object` and `record` filters now only accept an instance of the correct
16
+ class type or a subclass of the correct class. They no longer allow you to
17
+ check for included modules. ([how to upgrade](#object-and-record-filter-changes))
18
+ - The `interface` filter will now look for an ancestor of the value passed
19
+ based on the name of the interface or the value passed in the `from` option.
20
+ - The `InvalidClassError` has been replaced by `InvalidNameError`.
21
+ - When introspecting an array filter, the inner filter is referenced by :'0'
22
+ instead of the singularized version of the array filter name.
23
+
24
+ ## Added
25
+
26
+ - Implicit coercion of types are now supported in filters (e.g. to_str, to_int,
27
+ etc).
28
+ - The `interface` and `record` filters, when used as an inner filter for an
29
+ `array`, will have their `from/class` option set to a singularized version of
30
+ the `array` filter name.
31
+
32
+ ## Upgrading
33
+
34
+ ### Predicate Methods
35
+
36
+ We've removed the predicate methods that were automatically generated for each
37
+ input. They would return true if an input was not `nil`. They can be manually
38
+ replaced with that same check.
39
+
40
+ ```ruby
41
+ # v3.8
42
+ class Example < ActiveInteraction::Base
43
+ string :first_name
44
+
45
+ validates :first_name,
46
+ presence: true,
47
+ if: :first_name?
48
+
49
+ def execute
50
+ # ...
51
+ end
52
+ end
53
+
54
+ # v4.0
55
+ class Example < ActiveInteraction::Base
56
+ string :first_name
57
+
58
+ validates :first_name,
59
+ presence: true,
60
+ unless: 'first_name.nil?'
61
+
62
+ def execute
63
+ # ...
64
+ end
65
+ end
66
+ ```
67
+
68
+ ## Blank Values Treated As `nil` For Filters
69
+
70
+ In an effort to improve form support, strings that are `blank?` will
71
+ be converted into `nil` for all filters except `string` and `symbol`.
72
+ Previously, blank strings would have cased `:invalid_type` errors but
73
+ they'll now cause a `:missing` error which should be more form
74
+ friendly. If the filter has a default, the blank string will cause
75
+ the default to be used.
76
+
77
+ ```ruby
78
+ class Example < ActiveInteraction::Base
79
+ integer :i
80
+ boolean :b, default: false
81
+
82
+ def execute
83
+ [i, b]
84
+ end
85
+ end
86
+
87
+ # v3.8
88
+ Example.run(i: '', b: '').errors.details
89
+ => {:i=>[{:error=>:invalid_type, :type=>"integer"}], :b=>[{:error=>:invalid_type, :type=>"boolean"}]}
90
+
91
+ # v4.0
92
+ Example.run(i: '', b: '').errors.details
93
+ => {:i=>[{:error=>:missing}]}
94
+
95
+ # v3.8
96
+ Example.run(i: 0, b: '').errors.details
97
+ => {:b=>[{:error=>:invalid_type, :type=>"boolean"}]}
98
+
99
+ # v4.0
100
+ Example.run(i: 0, b: '').errors.details
101
+ => {}
102
+
103
+ Example.run(i: 0, b: '').result
104
+ => [0, false] # the default is used for `:b`
105
+ ```
106
+
107
+ ### Integer Parsing Base Now 10
108
+
109
+ Integers are parsed using `Integer`. By default this meant that when
110
+ strings were parsed, radix indicators (0, 0b, and 0x) were honored. Now
111
+ we're defaulting the base to `10`. This means all strings will be parsed
112
+ as though they are base 10.
113
+
114
+ ```ruby
115
+ class Example < ActiveInteraction::Base
116
+ integer :x
117
+
118
+ def execute
119
+ x
120
+ end
121
+ end
122
+
123
+ # v3.8
124
+ Example.run!(x: '010')
125
+ # => 8
126
+
127
+ # v4.0
128
+ Example.run!(x: '010')
129
+ # => 10
130
+ ```
131
+
132
+ If you want the old behavior that respected the radix you can pass `0`
133
+ as the base.
134
+
135
+ ```diff
136
+ - integer :x
137
+ + integer :x, base: 0
138
+ ```
139
+
140
+ With that change, we can see the radix is respected again.
141
+
142
+ ```ruby
143
+ # v4.0.0
144
+ Example.run!(x: '010')
145
+ # => 8
146
+ ```
147
+
148
+ ### Object and Record Filter Changes
149
+
150
+ The `object` and `record` filters used to be able to check for included modules
151
+ in addition to a class type. This has been removed. If you want any object that
152
+ has a particular module included, you'll need to use the newly expanded
153
+ `interface` filter.
154
+
1
155
  # [3.8.3][] (2020-04-22)
2
156
 
3
157
  ## Fixed
@@ -777,6 +931,7 @@ Example.run
777
931
 
778
932
  - Initial release.
779
933
 
934
+ [4.0.0]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.3...v4.0.0
780
935
  [3.8.3]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.2...v3.8.3
781
936
  [3.8.2]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.1...v3.8.2
782
937
  [3.8.1]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.0...v3.8.1
@@ -979,3 +1134,5 @@ Example.run
979
1134
  [#476]: https://github.com/AaronLasseigne/active_interaction/issues/476
980
1135
  [#479]: https://github.com/AaronLasseigne/active_interaction/issues/479
981
1136
  [#486]: https://github.com/AaronLasseigne/active_interaction/issues/486
1137
+ [#392]: https://github.com/AaronLasseigne/active_interaction/issues/392
1138
+ [#398]: https://github.com/AaronLasseigne/active_interaction/issues/398
data/README.md CHANGED
@@ -4,7 +4,7 @@ ActiveInteraction manages application-specific business logic.
4
4
  It's an implementation of the command pattern in Ruby.
5
5
 
6
6
  [![Version](https://img.shields.io/gem/v/active_interaction.svg?style=flat-square)](https://rubygems.org/gems/active_interaction)
7
- [![Build](https://img.shields.io/travis/AaronLasseigne/active_interaction.svg?style=flat-square)](https://travis-ci.org/AaronLasseigne/active_interaction)
7
+ [![Test](https://img.shields.io/github/workflow/status/AaronLasseigne/active_interaction/Test?label=Test&style=flat-square)](https://github.com/AaronLasseigne/active_interaction/actions?query=workflow%3ATest)
8
8
  [![Coverage](https://img.shields.io/coveralls/github/AaronLasseigne/active_interaction.svg?style=flat-square)](https://coveralls.io/r/orgsync/active_interaction)
9
9
  [![Climate](https://img.shields.io/codeclimate/maintainability/orgsync/active_interaction.svg?style=flat-square)](https://codeclimate.com/github/orgsync/active_interaction)
10
10
 
@@ -55,7 +55,6 @@ handles your verbs.
55
55
  - [Forms](#forms)
56
56
  - [Grouped inputs](#grouped-inputs)
57
57
  - [Optional inputs](#optional-inputs)
58
- - [Predicates](#predicates)
59
58
  - [Translations](#translations)
60
59
  - [Credits](#credits)
61
60
 
@@ -66,23 +65,19 @@ handles your verbs.
66
65
  Add it to your Gemfile:
67
66
 
68
67
  ``` rb
69
- gem 'active_interaction', '~> 3.8'
68
+ gem 'active_interaction', '~> 4.0'
70
69
  ```
71
70
 
72
71
  Or install it manually:
73
72
 
74
73
  ``` sh
75
- $ gem install active_interaction --version '~> 3.8'
74
+ $ gem install active_interaction --version '~> 4.0'
76
75
  ```
77
76
 
78
77
  This project uses [Semantic Versioning][]. Check out [GitHub releases][] for a
79
78
  detailed list of changes. For help upgrading to version 2, please read [the
80
79
  announcement post][].
81
80
 
82
- ActiveInteraction works with Ruby 2.0 through 2.6 and ActiveModel 4.0 through
83
- 6.0. If you want to use ActiveInteraction with an older version of Ruby or
84
- ActiveModel, use ActiveInteraction < 3.0.0.
85
-
86
81
  ## Basic usage
87
82
 
88
83
  To define an interaction, create a subclass of `ActiveInteraction::Base`. Then
@@ -241,7 +236,8 @@ ArrayInteraction.run!(toppings: [:cheese, 'pepperoni'])
241
236
  # => 2
242
237
  ```
243
238
 
244
- Use a block to constrain the types of elements an array can contain.
239
+ Use a block to constrain the types of elements an array can contain. Note that
240
+ you can only have one filter inside an array block, and it must not have a name.
245
241
 
246
242
  ``` rb
247
243
  array :birthdays do
@@ -249,19 +245,29 @@ array :birthdays do
249
245
  end
250
246
  ```
251
247
 
252
- Note that you can only have one filter inside an array block, and it must not
253
- have a name.
248
+ For `interface`, `object`, and `record` filters, the name of the array filter
249
+ will be singularized and used to determine the type of value passed. In the
250
+ example below, the objects passed would need to be of type `Cow`.
254
251
 
255
252
  ``` rb
256
253
  array :cows do
257
- object class: Cow
254
+ object
255
+ end
256
+ ```
257
+
258
+ You can override this by passing the necessary information to the inner filter.
259
+
260
+ ```ruby
261
+ array :managers do
262
+ object class: People
258
263
  end
259
264
  ```
260
265
 
261
266
  ### Boolean
262
267
 
263
- Boolean filters convert the strings `"1"` and `"true"` (case-insensitive) into
264
- `true`. They also convert `"0"` and `"false"` into `false`.
268
+ Boolean filters convert the strings `"1"`, `"true"`, and `"on"`
269
+ (case-insensitive) into `true`. They also convert `"0"`, `"false"`, and `"off"`
270
+ into `false`. Blank strings will be treated as `nil`.
265
271
 
266
272
  ``` rb
267
273
  class BooleanInteraction < ActiveInteraction::Base
@@ -353,8 +359,45 @@ hash :stuff,
353
359
 
354
360
  ### Interface
355
361
 
356
- Interface filters allow you to specify that an object must respond to a certain
357
- set of methods. This allows you to do duck typing with interactions.
362
+ Interface filters allow you to specify an interface that the passed value must
363
+ meet in order to pass. The name of the interface is used to look for a constant
364
+ inside the ancestor listing for the passed value. This allows for a variety of
365
+ checks depending on what's passed. Class instances are checked for an included
366
+ module or an inherited ancestor class. Classes are checked for an extended
367
+ module or an inherited ancestor class. Modules are checked for an extended
368
+ module.
369
+
370
+ ``` rb
371
+ class InterfaceInteraction < ActiveInteraction::Base
372
+ interface :exception
373
+
374
+ def execute
375
+ exception
376
+ end
377
+ end
378
+
379
+ InterfaceInteraction.run!(exception: Exception)
380
+ # ActiveInteraction::InvalidInteractionError: Exception is not a valid interface
381
+ InterfaceInteraction.run!(exception: NameError) # a subclass of Exception
382
+ # => NameError
383
+ ```
384
+
385
+ You can use `:from` to specify a class or module. This would be the equivalent
386
+ of what's above.
387
+
388
+ ```rb
389
+ class InterfaceInteraction < ActiveInteraction::Base
390
+ interface :error,
391
+ from: Exception
392
+
393
+ def execute
394
+ error
395
+ end
396
+ end
397
+ ```
398
+
399
+ You can also create an anonymous interface on the fly by passing the `methods`
400
+ option.
358
401
 
359
402
  ``` rb
360
403
  class InterfaceInteraction < ActiveInteraction::Base
@@ -378,30 +421,10 @@ InterfaceInteraction.run!(serializer: JSON)
378
421
  # => "{\"is_json\":true}"
379
422
  ```
380
423
 
381
- NOTE: The `methods` option is optional.
382
-
383
- ```rb
384
- class InterfaceInteraction < ActiveInteraction::Base
385
- interface :anything
386
-
387
- def execute
388
- anything.class
389
- end
390
- end
391
-
392
- require 'json'
393
-
394
- InterfaceInteraction.run!(anything: Hash.new)
395
- # => Hash
396
- InterfaceInteraction.run!
397
- # => NilClass
398
- ```
399
-
400
424
  ### Object
401
425
 
402
- Object filters allow you to require an instance of a particular class. It
403
- checks either `#is_a?` on the instance or `.===` on the class. Because of that,
404
- it also works with classes that have mixed modules in with `include`.
426
+ Object filters allow you to require an instance of a particular class or one of
427
+ its subclasses.
405
428
 
406
429
  ``` rb
407
430
  class Cow
@@ -438,8 +461,8 @@ object :dolly3,
438
461
  ```
439
462
 
440
463
  If you have value objects or you would like to build one object from another,
441
- you can use the `converter` option. It is only called if the value provided does
442
- not pass `#is_a?` and `.===` for the object class. The `converter` option
464
+ you can use the `converter` option. It is only called if the value provided is
465
+ not an instance of the class or one of its subclasses. The `converter` option
443
466
  accepts a symbol that specifies a class method on the object class or a proc.
444
467
  Both will be passed the value and any errors thrown inside the converter will
445
468
  cause the value to be considered invalid. Any returned value that is not the
@@ -466,13 +489,13 @@ ObjectInteraction.run!(ip_address: 1)
466
489
 
467
490
  ### Record
468
491
 
469
- Record filters allow you to require an instance of a particular class or a value
470
- that can be used to locate an instance of the object. It checks either `#is_a?`
471
- on the instance or `.===` on the class. If the value does not match, it will
472
- call `find` on the class of the record. This is particularly useful when working
473
- with ActiveRecord objects. Like an object filter, the class is derived from the
474
- name passed but can be specified with the `class` option. The value given to the
475
- `default` option will also be found.
492
+ Record filters allow you to require an instance of a particular class (or one
493
+ of its subclasses) or a value that can be used to locate an instance of the
494
+ object. If the value does not match, it will call `find` on the class of the
495
+ record. This is particularly useful when working with ActiveRecord objects.
496
+ Like an object filter, the class is derived from the name passed but can be
497
+ specified with the `class` option. The value given to the `default` option will
498
+ also be found.
476
499
 
477
500
  ``` rb
478
501
  class RecordInteraction < ActiveInteraction::Base
@@ -542,9 +565,10 @@ SymbolInteraction.run!(method: :object_id)
542
565
  ### Dates and times
543
566
 
544
567
  Filters that work with dates and times behave similarly. By default, they all
545
- convert strings into their expected data types using `.parse`. If you give the
546
- `format` option, they will instead convert strings using `.strptime`. Note that
547
- formats won't work with `DateTime` and `Time` filters if a time zone is set.
568
+ convert strings into their expected data types using `.parse`. Blank strings
569
+ will be treated as `nil`. If you give the `format` option, they will instead
570
+ convert strings using `.strptime`. Note that formats won't work with `DateTime`
571
+ and `Time` filters if a time zone is set.
548
572
 
549
573
  #### Date
550
574
 
@@ -618,7 +642,8 @@ time :start,
618
642
  ### Numbers
619
643
 
620
644
  All numeric filters accept numeric input. They will also convert strings using
621
- the appropriate method from `Kernel` (like `.Float`).
645
+ the appropriate method from `Kernel` (like `.Float`). Blank strings will be
646
+ treated as `nil`.
622
647
 
623
648
  #### Decimal
624
649
 
@@ -679,24 +704,27 @@ IntegerInteraction.run!(limit: 10)
679
704
  ```
680
705
 
681
706
  When a `String` is passed into an `integer` input, the value will be coerced.
682
- Coercion is based on `Kernel#Integer` which attempts to detect the base being used.
683
- However, you may want to specify the `base` for the conversion to something more
684
- sensible (e.g. `base: 10`).
707
+ A default base of `10` is used though it may be overridden with the `base` option.
708
+ If a base of `0` is provided, the coercion will respect radix indicators present
709
+ in the string.
685
710
 
686
711
  ``` rb
687
712
  class IntegerInteraction < ActiveInteraction::Base
688
- integer :limit1, base: 10
689
- integer :limit2
713
+ integer :limit1
714
+ integer :limit2, base: 8
715
+ integer :limit3, base: 0
690
716
 
691
717
  def execute
692
- [limit1, limit2]
718
+ [limit1, limit2, limit3]
693
719
  end
694
720
  end
695
721
 
696
- IntegerInteraction.run!(limit1: "08", limit2: 8)
697
- # => [8, 8]
698
- IntegerInteraction.run!(limit1: "08", limit2: "08")
699
- # ArgumentError: invalid value for Integer(): "08"
722
+ IntegerInteraction.run!(limit1: 71, limit2: 71, limit3: 71)
723
+ # => [71, 71, 71]
724
+ IntegerInteraction.run!(limit1: "071", limit2: "071", limit3: "0x71")
725
+ # => [71, 57, 113]
726
+ IntegerInteraction.run!(limit1: "08", limit2: "08", limit3: "08")
727
+ ActiveInteraction::InvalidInteractionError: Limit2 is not a valid integer, Limit3 is not a valid integer
700
728
  ```
701
729
 
702
730
  ## Rails
@@ -940,10 +968,6 @@ The interaction that updates accounts is more complicated than the others. It
940
968
  requires an account to update, but the other inputs are optional. If they're
941
969
  missing, it'll ignore those attributes. If they're present, it'll update them.
942
970
 
943
- ActiveInteraction generates predicate methods (like `#first_name?`) for your
944
- inputs. They will return `false` if the input is `nil` and `true` otherwise.
945
- Skip to [the predicates section](#predicates) for more information about them.
946
-
947
971
  ``` rb
948
972
  class UpdateAccount < ActiveInteraction::Base
949
973
  object :account
@@ -953,14 +977,14 @@ class UpdateAccount < ActiveInteraction::Base
953
977
 
954
978
  validates :first_name,
955
979
  presence: true,
956
- if: :first_name?
980
+ unless: 'first_name.nil?'
957
981
  validates :last_name,
958
982
  presence: true,
959
- if: :last_name?
983
+ unless: 'last_name.nil?'
960
984
 
961
985
  def execute
962
- account.first_name = first_name if first_name?
963
- account.last_name = last_name if last_name?
986
+ account.first_name = first_name if first_name.present?
987
+ account.last_name = last_name if last_name.present?
964
988
 
965
989
  unless account.save
966
990
  errors.merge!(account.errors)
@@ -1177,9 +1201,6 @@ def execute
1177
1201
  end
1178
1202
  ```
1179
1203
 
1180
- These types of errors will become standard with Rails 5. ActiveInteraction's
1181
- implementation is based off of [active_model-errors_details][].
1182
-
1183
1204
  ActiveInteraction also supports merging errors. This is useful if you want to
1184
1205
  delegate validation to some other object. For example, if you have an
1185
1206
  interaction that updates a record, you might want that record to validate
@@ -1375,41 +1396,6 @@ UpdateUser.run!(user: user, birthday: nil)
1375
1396
  UpdateUser.run!(user: user, birthday: Date.new(2000, 1, 2))
1376
1397
  ```
1377
1398
 
1378
- ### Predicates
1379
-
1380
- ActiveInteraction creates a predicate method for every input defined by a
1381
- filter. So if you have an input called `foo`, there will be a predicate method
1382
- called `#foo?`. That method will tell you if the input was given (that is, if
1383
- it was not `nil`).
1384
-
1385
- ``` rb
1386
- class SayHello < ActiveInteraction::Base
1387
- string :name,
1388
- default: nil
1389
-
1390
- def execute
1391
- if name?
1392
- "Hello, #{name}!"
1393
- else
1394
- "Howdy, stranger!"
1395
- end
1396
- end
1397
- end
1398
-
1399
- SayHello.run!(name: nil)
1400
- # => "Howdy, stranger!"
1401
- SayHello.run!(name: 'Taylor')
1402
- # => "Hello, Taylor!"
1403
- ```
1404
-
1405
- This can be confusing for boolean inputs. If you have some boolean input `foo`,
1406
- then the actual value of that input is available through `foo`. The associated
1407
- predicate method, `#foo?`, will tell you if that value is not `nil`. So it will
1408
- only be `false` if the input is optional and happens to be `nil`.
1409
-
1410
- See [the optional inputs section][] for help on determining if an input was
1411
- present in the input hash instead of just `nil`.
1412
-
1413
1399
  ### Translations
1414
1400
 
1415
1401
  ActiveInteraction is i18n aware out of the box! All you have to do is add