active_interaction 3.7.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: acc5f59cdd588429a58556cea7b70aa0c43a6a13c523a682cac266cfc7ab76a1
|
4
|
+
data.tar.gz: 9a58db1735b436ae91a70baf9c2eab9ef4851a20a9e51c05c6f243af6e3c282b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c78b1f82d8593a238a2076f7351146e51079d163d963cc830d9e086bbc82bd791fbc95527d4fc829e3c38039bb77ce06fefe82520f5b6f2148a64384a8e3a339
|
7
|
+
data.tar.gz: 362a8b86512c8ef05d9582a377000e06e2b8b0855c112458020911fa77477c3c98cd10555e81d259cfc767f79c1eb8b03e9ec12124cfca38c552208006e1a70a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,182 @@
|
|
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
|
+
|
155
|
+
# [3.8.3][] (2020-04-22)
|
156
|
+
|
157
|
+
## Fixed
|
158
|
+
|
159
|
+
- [486][] `valid?` returns true if block not called and error added in execute around callback.
|
160
|
+
|
161
|
+
# [3.8.2][] (2020-04-22)
|
162
|
+
|
163
|
+
## Fixed
|
164
|
+
|
165
|
+
- [479][] Composed interactions that throw errors now show a complete backtrace instead of ending at the `run!` of the outermost interaction.
|
166
|
+
|
167
|
+
# [3.8.1][] (2020-04-04)
|
168
|
+
|
169
|
+
## Fixed
|
170
|
+
|
171
|
+
- The implementation for providing a failing interaction on `InvalidInteractionError` was a breaking API change. It now works without breaking the API.
|
172
|
+
|
173
|
+
# [3.8.0][] (2020-02-28)
|
174
|
+
|
175
|
+
## Added
|
176
|
+
|
177
|
+
- [#477][] `InvalidInteractionError` now provides access to the failing interaction by calling `interaction`.
|
178
|
+
- [#476][] Update `given?` to check for items in an array by passing an index.
|
179
|
+
|
1
180
|
# [3.7.1][] (2019-03-20)
|
2
181
|
|
3
182
|
## Fixed
|
@@ -752,6 +931,11 @@ Example.run
|
|
752
931
|
|
753
932
|
- Initial release.
|
754
933
|
|
934
|
+
[4.0.0]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.3...v4.0.0
|
935
|
+
[3.8.3]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.2...v3.8.3
|
936
|
+
[3.8.2]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.1...v3.8.2
|
937
|
+
[3.8.1]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.0...v3.8.1
|
938
|
+
[3.8.0]: https://github.com/AaronLasseigne/active_interaction/compare/v3.7.1...v3.8.0
|
755
939
|
[3.7.1]: https://github.com/AaronLasseigne/active_interaction/compare/v3.7.0...v3.7.1
|
756
940
|
[3.7.0]: https://github.com/AaronLasseigne/active_interaction/compare/v3.6.2...v3.7.0
|
757
941
|
[3.6.2]: https://github.com/AaronLasseigne/active_interaction/compare/v3.6.1...v3.6.2
|
@@ -946,3 +1130,9 @@ Example.run
|
|
946
1130
|
[#454]: https://github.com/AaronLasseigne/active_interaction/pull/454
|
947
1131
|
[#455]: https://github.com/AaronLasseigne/active_interaction/pull/455
|
948
1132
|
[#457]: https://github.com/AaronLasseigne/active_interaction/issues/457
|
1133
|
+
[#477]: https://github.com/AaronLasseigne/active_interaction/issues/477
|
1134
|
+
[#476]: https://github.com/AaronLasseigne/active_interaction/issues/476
|
1135
|
+
[#479]: https://github.com/AaronLasseigne/active_interaction/issues/479
|
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/CONTRIBUTING.md
CHANGED
@@ -10,4 +10,4 @@
|
|
10
10
|
|
11
11
|
Running the tests using `rake` (with no args) will also check for style issues in the code. Ideally all submissions would pass these checks. If the code style is causing issues (particularly the method or class size) we can work with you to correct it. Don't let it stop you from contributing.
|
12
12
|
|
13
|
-
[fork]: https://github.com/
|
13
|
+
[fork]: https://github.com/AaronLasseigne/active_interaction/fork
|
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
|
-
[![
|
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', '~>
|
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 '~>
|
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
|
-
|
253
|
-
|
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
|
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 `"
|
264
|
-
`true`. They also convert `"0"` and `"
|
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
|
357
|
-
|
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
|
@@ -380,9 +423,8 @@ InterfaceInteraction.run!(serializer: JSON)
|
|
380
423
|
|
381
424
|
### Object
|
382
425
|
|
383
|
-
Object filters allow you to require an instance of a particular class
|
384
|
-
|
385
|
-
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.
|
386
428
|
|
387
429
|
``` rb
|
388
430
|
class Cow
|
@@ -419,8 +461,8 @@ object :dolly3,
|
|
419
461
|
```
|
420
462
|
|
421
463
|
If you have value objects or you would like to build one object from another,
|
422
|
-
you can use the `converter` option. It is only called if the value provided
|
423
|
-
not
|
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
|
424
466
|
accepts a symbol that specifies a class method on the object class or a proc.
|
425
467
|
Both will be passed the value and any errors thrown inside the converter will
|
426
468
|
cause the value to be considered invalid. Any returned value that is not the
|
@@ -447,13 +489,13 @@ ObjectInteraction.run!(ip_address: 1)
|
|
447
489
|
|
448
490
|
### Record
|
449
491
|
|
450
|
-
Record filters allow you to require an instance of a particular class or
|
451
|
-
that can be used to locate an instance of the
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
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.
|
457
499
|
|
458
500
|
``` rb
|
459
501
|
class RecordInteraction < ActiveInteraction::Base
|
@@ -523,9 +565,10 @@ SymbolInteraction.run!(method: :object_id)
|
|
523
565
|
### Dates and times
|
524
566
|
|
525
567
|
Filters that work with dates and times behave similarly. By default, they all
|
526
|
-
convert strings into their expected data types using `.parse`.
|
527
|
-
`format` option, they will instead
|
528
|
-
formats won't work with `DateTime`
|
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.
|
529
572
|
|
530
573
|
#### Date
|
531
574
|
|
@@ -599,7 +642,8 @@ time :start,
|
|
599
642
|
### Numbers
|
600
643
|
|
601
644
|
All numeric filters accept numeric input. They will also convert strings using
|
602
|
-
the appropriate method from `Kernel` (like `.Float`).
|
645
|
+
the appropriate method from `Kernel` (like `.Float`). Blank strings will be
|
646
|
+
treated as `nil`.
|
603
647
|
|
604
648
|
#### Decimal
|
605
649
|
|
@@ -660,24 +704,27 @@ IntegerInteraction.run!(limit: 10)
|
|
660
704
|
```
|
661
705
|
|
662
706
|
When a `String` is passed into an `integer` input, the value will be coerced.
|
663
|
-
|
664
|
-
|
665
|
-
|
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.
|
666
710
|
|
667
711
|
``` rb
|
668
712
|
class IntegerInteraction < ActiveInteraction::Base
|
669
|
-
integer :limit1
|
670
|
-
integer :limit2
|
671
|
-
|
713
|
+
integer :limit1
|
714
|
+
integer :limit2, base: 8
|
715
|
+
integer :limit3, base: 0
|
716
|
+
|
672
717
|
def execute
|
673
|
-
[limit1, limit2]
|
718
|
+
[limit1, limit2, limit3]
|
674
719
|
end
|
675
720
|
end
|
676
721
|
|
677
|
-
IntegerInteraction.run!(limit1:
|
678
|
-
# => [
|
679
|
-
IntegerInteraction.run!(limit1: "
|
680
|
-
#
|
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
|
681
728
|
```
|
682
729
|
|
683
730
|
## Rails
|
@@ -921,10 +968,6 @@ The interaction that updates accounts is more complicated than the others. It
|
|
921
968
|
requires an account to update, but the other inputs are optional. If they're
|
922
969
|
missing, it'll ignore those attributes. If they're present, it'll update them.
|
923
970
|
|
924
|
-
ActiveInteraction generates predicate methods (like `#first_name?`) for your
|
925
|
-
inputs. They will return `false` if the input is `nil` and `true` otherwise.
|
926
|
-
Skip to [the predicates section](#predicates) for more information about them.
|
927
|
-
|
928
971
|
``` rb
|
929
972
|
class UpdateAccount < ActiveInteraction::Base
|
930
973
|
object :account
|
@@ -934,14 +977,14 @@ class UpdateAccount < ActiveInteraction::Base
|
|
934
977
|
|
935
978
|
validates :first_name,
|
936
979
|
presence: true,
|
937
|
-
|
980
|
+
unless: 'first_name.nil?'
|
938
981
|
validates :last_name,
|
939
982
|
presence: true,
|
940
|
-
|
983
|
+
unless: 'last_name.nil?'
|
941
984
|
|
942
985
|
def execute
|
943
|
-
account.first_name = first_name if first_name?
|
944
|
-
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?
|
945
988
|
|
946
989
|
unless account.save
|
947
990
|
errors.merge!(account.errors)
|
@@ -1158,9 +1201,6 @@ def execute
|
|
1158
1201
|
end
|
1159
1202
|
```
|
1160
1203
|
|
1161
|
-
These types of errors will become standard with Rails 5. ActiveInteraction's
|
1162
|
-
implementation is based off of [active_model-errors_details][].
|
1163
|
-
|
1164
1204
|
ActiveInteraction also supports merging errors. This is useful if you want to
|
1165
1205
|
delegate validation to some other object. For example, if you have an
|
1166
1206
|
interaction that updates a record, you might want that record to validate
|
@@ -1322,7 +1362,8 @@ whether a value was passed to `run` or the result of a filter default. In
|
|
1322
1362
|
particular, it is useful when `nil` is an acceptable value. For example, you
|
1323
1363
|
may optionally track your users' birthdays. You can use the `given?` predicate
|
1324
1364
|
to see if an input was even passed to `run`. With `given?` you can also check
|
1325
|
-
the input of a hash filter by passing a series of keys to
|
1365
|
+
the input of a hash or array filter by passing a series of keys or indexes to
|
1366
|
+
check.
|
1326
1367
|
|
1327
1368
|
``` rb
|
1328
1369
|
class UpdateUser < ActiveInteraction::Base
|
@@ -1355,41 +1396,6 @@ UpdateUser.run!(user: user, birthday: nil)
|
|
1355
1396
|
UpdateUser.run!(user: user, birthday: Date.new(2000, 1, 2))
|
1356
1397
|
```
|
1357
1398
|
|
1358
|
-
### Predicates
|
1359
|
-
|
1360
|
-
ActiveInteraction creates a predicate method for every input defined by a
|
1361
|
-
filter. So if you have an input called `foo`, there will be a predicate method
|
1362
|
-
called `#foo?`. That method will tell you if the input was given (that is, if
|
1363
|
-
it was not `nil`).
|
1364
|
-
|
1365
|
-
``` rb
|
1366
|
-
class SayHello < ActiveInteraction::Base
|
1367
|
-
string :name,
|
1368
|
-
default: nil
|
1369
|
-
|
1370
|
-
def execute
|
1371
|
-
if name?
|
1372
|
-
"Hello, #{name}!"
|
1373
|
-
else
|
1374
|
-
"Howdy, stranger!"
|
1375
|
-
end
|
1376
|
-
end
|
1377
|
-
end
|
1378
|
-
|
1379
|
-
SayHello.run!(name: nil)
|
1380
|
-
# => "Howdy, stranger!"
|
1381
|
-
SayHello.run!(name: 'Taylor')
|
1382
|
-
# => "Hello, Taylor!"
|
1383
|
-
```
|
1384
|
-
|
1385
|
-
This can be confusing for boolean inputs. If you have some boolean input `foo`,
|
1386
|
-
then the actual value of that input is available through `foo`. The associated
|
1387
|
-
predicate method, `#foo?`, will tell you if that value is not `nil`. So it will
|
1388
|
-
only be `false` if the input is optional and happens to be `nil`.
|
1389
|
-
|
1390
|
-
See [the optional inputs section][] for help on determining if an input was
|
1391
|
-
present in the input hash instead of just `nil`.
|
1392
|
-
|
1393
1399
|
### Translations
|
1394
1400
|
|
1395
1401
|
ActiveInteraction is i18n aware out of the box! All you have to do is add
|