active_interaction 3.8.3 → 4.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +193 -0
- data/README.md +97 -116
- data/lib/active_interaction.rb +2 -7
- data/lib/active_interaction/base.rb +44 -67
- 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 +6 -12
- data/lib/active_interaction/errors.rb +4 -19
- data/lib/active_interaction/filter.rb +66 -37
- data/lib/active_interaction/filter_column.rb +0 -3
- data/lib/active_interaction/filters/abstract_date_time_filter.rb +38 -36
- data/lib/active_interaction/filters/abstract_numeric_filter.rb +27 -17
- data/lib/active_interaction/filters/array_filter.rb +59 -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 +24 -19
- data/lib/active_interaction/grouped_input.rb +0 -3
- data/lib/active_interaction/inputs.rb +120 -0
- data/lib/active_interaction/modules/validation.rb +9 -21
- data/lib/active_interaction/version.rb +1 -3
- data/spec/active_interaction/base_spec.rb +38 -99
- 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 +0 -2
- data/spec/active_interaction/concerns/missable_spec.rb +0 -2
- data/spec/active_interaction/concerns/runnable_spec.rb +9 -13
- data/spec/active_interaction/errors_spec.rb +4 -25
- 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 +62 -13
- 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} +35 -5
- data/spec/active_interaction/integration/array_interaction_spec.rb +18 -22
- 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 +1 -3
- 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 -12
- data/spec/support/concerns.rb +0 -2
- data/spec/support/filters.rb +13 -9
- data/spec/support/interactions.rb +22 -14
- metadata +92 -62
- data/lib/active_interaction/backports.rb +0 -59
- data/lib/active_interaction/filters/abstract_filter.rb +0 -19
- data/lib/active_interaction/modules/input_processor.rb +0 -52
- 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: 24af31782cca3b666b2f211506cb3ca39e362ffcb665ae509bda892b13e65934
|
|
4
|
+
data.tar.gz: 3a139e271e9d19ac23cdea62a5bbe882889f50483647951289623b8f3aaaf97f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 574d84a7a67526dcb2b7f64ca885d6cccb3115612e731b4091bd1bb122446a88ce81ad791196c6bd33555122e9b2c8b07ac1924cecbe400f4d541906274fcd3c
|
|
7
|
+
data.tar.gz: 1260eae401d19342ef4b8e2ada334553e7b99672b3257ec9b5880d0c6566eb8dc86e8de9fc5c5a3d0ed37485f86fc88cdb3adc2abe6299ac60d049f1d0713474
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,184 @@
|
|
|
1
|
+
# [4.0.4][] (2021-07-03)
|
|
2
|
+
|
|
3
|
+
## Fix
|
|
4
|
+
|
|
5
|
+
- [#510][] - Hash parameters failed when working outside of Rails.
|
|
6
|
+
- [#511][] - Nested filters with options but no `:class` failed to have `:class` automatically added.
|
|
7
|
+
|
|
8
|
+
# [4.0.3][] (2021-06-24)
|
|
9
|
+
|
|
10
|
+
## Fix
|
|
11
|
+
|
|
12
|
+
- [#499][] - `given?` now recognizes multi-part date inputs by their primary key name
|
|
13
|
+
- [#493][] - `compose` now properly accepts `Inputs`
|
|
14
|
+
|
|
15
|
+
# [4.0.2][] (2021-06-22)
|
|
16
|
+
|
|
17
|
+
## Fix
|
|
18
|
+
|
|
19
|
+
- [#505][] - Nested Interface filters using the `:methods` option threw an error.
|
|
20
|
+
|
|
21
|
+
# [4.0.1][] (2021-05-26)
|
|
22
|
+
|
|
23
|
+
## Fix
|
|
24
|
+
|
|
25
|
+
- Fix regression of filter name relaxing.
|
|
26
|
+
- [#495][] - Fix time filter ignoring time zones
|
|
27
|
+
|
|
28
|
+
# [4.0.0][] (2021-01-10)
|
|
29
|
+
|
|
30
|
+
## Changed
|
|
31
|
+
|
|
32
|
+
- drop support for Ruby < 2.5, added support for Ruby 3.0
|
|
33
|
+
- drop support for Rails < 5.0, added support for Rails 6.1
|
|
34
|
+
- [#398][] - Predicate methods have been removed.
|
|
35
|
+
([how to upgrade](#predicate-methods))
|
|
36
|
+
- [#412][] - Filters will now treat blank string values as `nil`
|
|
37
|
+
(except `string` and `symbol`). ([how to upgrade](#blank-values-treated-as-nil-for-filters))
|
|
38
|
+
- [#392][] - Integer parsing now defaults the base to 10.
|
|
39
|
+
([how to upgrade](#integer-parsing-base-now-10))
|
|
40
|
+
- The `inputs` method now returns an `ActiveInteraction::Input` instead of a
|
|
41
|
+
hash. The `ActiveInteraction::Input` class still responds to all hash methods.
|
|
42
|
+
- The `object` and `record` filters now only accept an instance of the correct
|
|
43
|
+
class type or a subclass of the correct class. They no longer allow you to
|
|
44
|
+
check for included modules. ([how to upgrade](#object-and-record-filter-changes))
|
|
45
|
+
- The `interface` filter will now look for an ancestor of the value passed
|
|
46
|
+
based on the name of the interface or the value passed in the `from` option.
|
|
47
|
+
- The `InvalidClassError` has been replaced by `InvalidNameError`.
|
|
48
|
+
- When introspecting an array filter, the inner filter is referenced by :'0'
|
|
49
|
+
instead of the singularized version of the array filter name.
|
|
50
|
+
|
|
51
|
+
## Added
|
|
52
|
+
|
|
53
|
+
- Implicit coercion of types are now supported in filters (e.g. to_str, to_int,
|
|
54
|
+
etc).
|
|
55
|
+
- The `interface` and `record` filters, when used as an inner filter for an
|
|
56
|
+
`array`, will have their `from/class` option set to a singularized version of
|
|
57
|
+
the `array` filter name.
|
|
58
|
+
|
|
59
|
+
## Upgrading
|
|
60
|
+
|
|
61
|
+
### Predicate Methods
|
|
62
|
+
|
|
63
|
+
We've removed the predicate methods that were automatically generated for each
|
|
64
|
+
input. They would return true if an input was not `nil`. They can be manually
|
|
65
|
+
replaced with that same check.
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
# v3.8
|
|
69
|
+
class Example < ActiveInteraction::Base
|
|
70
|
+
string :first_name
|
|
71
|
+
|
|
72
|
+
validates :first_name,
|
|
73
|
+
presence: true,
|
|
74
|
+
if: :first_name?
|
|
75
|
+
|
|
76
|
+
def execute
|
|
77
|
+
# ...
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# v4.0
|
|
82
|
+
class Example < ActiveInteraction::Base
|
|
83
|
+
string :first_name
|
|
84
|
+
|
|
85
|
+
validates :first_name,
|
|
86
|
+
presence: true,
|
|
87
|
+
unless: -> { first_name.nil? }
|
|
88
|
+
|
|
89
|
+
def execute
|
|
90
|
+
# ...
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Blank Values Treated As `nil` For Filters
|
|
96
|
+
|
|
97
|
+
In an effort to improve form support, strings that are `blank?` will
|
|
98
|
+
be converted into `nil` for all filters except `string` and `symbol`.
|
|
99
|
+
Previously, blank strings would have cased `:invalid_type` errors but
|
|
100
|
+
they'll now cause a `:missing` error which should be more form
|
|
101
|
+
friendly. If the filter has a default, the blank string will cause
|
|
102
|
+
the default to be used.
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
class Example < ActiveInteraction::Base
|
|
106
|
+
integer :i
|
|
107
|
+
boolean :b, default: false
|
|
108
|
+
|
|
109
|
+
def execute
|
|
110
|
+
[i, b]
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# v3.8
|
|
115
|
+
Example.run(i: '', b: '').errors.details
|
|
116
|
+
=> {:i=>[{:error=>:invalid_type, :type=>"integer"}], :b=>[{:error=>:invalid_type, :type=>"boolean"}]}
|
|
117
|
+
|
|
118
|
+
# v4.0
|
|
119
|
+
Example.run(i: '', b: '').errors.details
|
|
120
|
+
=> {:i=>[{:error=>:missing}]}
|
|
121
|
+
|
|
122
|
+
# v3.8
|
|
123
|
+
Example.run(i: 0, b: '').errors.details
|
|
124
|
+
=> {:b=>[{:error=>:invalid_type, :type=>"boolean"}]}
|
|
125
|
+
|
|
126
|
+
# v4.0
|
|
127
|
+
Example.run(i: 0, b: '').errors.details
|
|
128
|
+
=> {}
|
|
129
|
+
|
|
130
|
+
Example.run(i: 0, b: '').result
|
|
131
|
+
=> [0, false] # the default is used for `:b`
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Integer Parsing Base Now 10
|
|
135
|
+
|
|
136
|
+
Integers are parsed using `Integer`. By default this meant that when
|
|
137
|
+
strings were parsed, radix indicators (0, 0b, and 0x) were honored. Now
|
|
138
|
+
we're defaulting the base to `10`. This means all strings will be parsed
|
|
139
|
+
as though they are base 10.
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
class Example < ActiveInteraction::Base
|
|
143
|
+
integer :x
|
|
144
|
+
|
|
145
|
+
def execute
|
|
146
|
+
x
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# v3.8
|
|
151
|
+
Example.run!(x: '010')
|
|
152
|
+
# => 8
|
|
153
|
+
|
|
154
|
+
# v4.0
|
|
155
|
+
Example.run!(x: '010')
|
|
156
|
+
# => 10
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
If you want the old behavior that respected the radix you can pass `0`
|
|
160
|
+
as the base.
|
|
161
|
+
|
|
162
|
+
```diff
|
|
163
|
+
- integer :x
|
|
164
|
+
+ integer :x, base: 0
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
With that change, we can see the radix is respected again.
|
|
168
|
+
|
|
169
|
+
```ruby
|
|
170
|
+
# v4.0.0
|
|
171
|
+
Example.run!(x: '010')
|
|
172
|
+
# => 8
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Object and Record Filter Changes
|
|
176
|
+
|
|
177
|
+
The `object` and `record` filters used to be able to check for included modules
|
|
178
|
+
in addition to a class type. This has been removed. If you want any object that
|
|
179
|
+
has a particular module included, you'll need to use the newly expanded
|
|
180
|
+
`interface` filter.
|
|
181
|
+
|
|
1
182
|
# [3.8.3][] (2020-04-22)
|
|
2
183
|
|
|
3
184
|
## Fixed
|
|
@@ -777,6 +958,11 @@ Example.run
|
|
|
777
958
|
|
|
778
959
|
- Initial release.
|
|
779
960
|
|
|
961
|
+
[4.0.4]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.3...v4.0.4
|
|
962
|
+
[4.0.3]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.2...v4.0.3
|
|
963
|
+
[4.0.2]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.1...v4.0.2
|
|
964
|
+
[4.0.1]: https://github.com/AaronLasseigne/active_interaction/compare/v4.0.0...v4.0.1
|
|
965
|
+
[4.0.0]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.3...v4.0.0
|
|
780
966
|
[3.8.3]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.2...v3.8.3
|
|
781
967
|
[3.8.2]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.1...v3.8.2
|
|
782
968
|
[3.8.1]: https://github.com/AaronLasseigne/active_interaction/compare/v3.8.0...v3.8.1
|
|
@@ -979,3 +1165,10 @@ Example.run
|
|
|
979
1165
|
[#476]: https://github.com/AaronLasseigne/active_interaction/issues/476
|
|
980
1166
|
[#479]: https://github.com/AaronLasseigne/active_interaction/issues/479
|
|
981
1167
|
[#486]: https://github.com/AaronLasseigne/active_interaction/issues/486
|
|
1168
|
+
[#392]: https://github.com/AaronLasseigne/active_interaction/issues/392
|
|
1169
|
+
[#398]: https://github.com/AaronLasseigne/active_interaction/issues/398
|
|
1170
|
+
[#495]: https://github.com/AaronLasseigne/active_interaction/issues/495
|
|
1171
|
+
[#505]: https://github.com/AaronLasseigne/active_interaction/issues/505
|
|
1172
|
+
[#499]: https://github.com/AaronLasseigne/active_interaction/issues/499
|
|
1173
|
+
[#493]: https://github.com/AaronLasseigne/active_interaction/issues/493
|
|
1174
|
+
[#510]: https://github.com/AaronLasseigne/active_interaction/issues/510
|
data/README.md
CHANGED
|
@@ -4,8 +4,7 @@ ActiveInteraction manages application-specific business logic.
|
|
|
4
4
|
It's an implementation of the command pattern in Ruby.
|
|
5
5
|
|
|
6
6
|
[](https://rubygems.org/gems/active_interaction)
|
|
7
|
-
[](https://coveralls.io/r/orgsync/active_interaction)
|
|
7
|
+
[](https://github.com/AaronLasseigne/active_interaction/actions?query=workflow%3ATest)
|
|
9
8
|
[](https://codeclimate.com/github/orgsync/active_interaction)
|
|
10
9
|
|
|
11
10
|
---
|
|
@@ -55,34 +54,29 @@ handles your verbs.
|
|
|
55
54
|
- [Forms](#forms)
|
|
56
55
|
- [Grouped inputs](#grouped-inputs)
|
|
57
56
|
- [Optional inputs](#optional-inputs)
|
|
58
|
-
- [Predicates](#predicates)
|
|
59
57
|
- [Translations](#translations)
|
|
60
58
|
- [Credits](#credits)
|
|
61
59
|
|
|
62
|
-
[
|
|
60
|
+
[API Documentation][]
|
|
63
61
|
|
|
64
62
|
## Installation
|
|
65
63
|
|
|
66
64
|
Add it to your Gemfile:
|
|
67
65
|
|
|
68
66
|
``` rb
|
|
69
|
-
gem 'active_interaction', '~>
|
|
67
|
+
gem 'active_interaction', '~> 4.0'
|
|
70
68
|
```
|
|
71
69
|
|
|
72
70
|
Or install it manually:
|
|
73
71
|
|
|
74
72
|
``` sh
|
|
75
|
-
$ gem install active_interaction --version '~>
|
|
73
|
+
$ gem install active_interaction --version '~> 4.0'
|
|
76
74
|
```
|
|
77
75
|
|
|
78
76
|
This project uses [Semantic Versioning][]. Check out [GitHub releases][] for a
|
|
79
77
|
detailed list of changes. For help upgrading to version 2, please read [the
|
|
80
78
|
announcement post][].
|
|
81
79
|
|
|
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
80
|
## Basic usage
|
|
87
81
|
|
|
88
82
|
To define an interaction, create a subclass of `ActiveInteraction::Base`. Then
|
|
@@ -241,7 +235,8 @@ ArrayInteraction.run!(toppings: [:cheese, 'pepperoni'])
|
|
|
241
235
|
# => 2
|
|
242
236
|
```
|
|
243
237
|
|
|
244
|
-
Use a block to constrain the types of elements an array can contain.
|
|
238
|
+
Use a block to constrain the types of elements an array can contain. Note that
|
|
239
|
+
you can only have one filter inside an array block, and it must not have a name.
|
|
245
240
|
|
|
246
241
|
``` rb
|
|
247
242
|
array :birthdays do
|
|
@@ -249,19 +244,29 @@ array :birthdays do
|
|
|
249
244
|
end
|
|
250
245
|
```
|
|
251
246
|
|
|
252
|
-
|
|
253
|
-
|
|
247
|
+
For `interface`, `object`, and `record` filters, the name of the array filter
|
|
248
|
+
will be singularized and used to determine the type of value passed. In the
|
|
249
|
+
example below, the objects passed would need to be of type `Cow`.
|
|
254
250
|
|
|
255
251
|
``` rb
|
|
256
252
|
array :cows do
|
|
257
|
-
object
|
|
253
|
+
object
|
|
254
|
+
end
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
You can override this by passing the necessary information to the inner filter.
|
|
258
|
+
|
|
259
|
+
```ruby
|
|
260
|
+
array :managers do
|
|
261
|
+
object class: People
|
|
258
262
|
end
|
|
259
263
|
```
|
|
260
264
|
|
|
261
265
|
### Boolean
|
|
262
266
|
|
|
263
|
-
Boolean filters convert the strings `"1"` and `"
|
|
264
|
-
`true`. They also convert `"0"` and `"
|
|
267
|
+
Boolean filters convert the strings `"1"`, `"true"`, and `"on"`
|
|
268
|
+
(case-insensitive) into `true`. They also convert `"0"`, `"false"`, and `"off"`
|
|
269
|
+
into `false`. Blank strings will be treated as `nil`.
|
|
265
270
|
|
|
266
271
|
``` rb
|
|
267
272
|
class BooleanInteraction < ActiveInteraction::Base
|
|
@@ -353,8 +358,45 @@ hash :stuff,
|
|
|
353
358
|
|
|
354
359
|
### Interface
|
|
355
360
|
|
|
356
|
-
Interface filters allow you to specify
|
|
357
|
-
|
|
361
|
+
Interface filters allow you to specify an interface that the passed value must
|
|
362
|
+
meet in order to pass. The name of the interface is used to look for a constant
|
|
363
|
+
inside the ancestor listing for the passed value. This allows for a variety of
|
|
364
|
+
checks depending on what's passed. Class instances are checked for an included
|
|
365
|
+
module or an inherited ancestor class. Classes are checked for an extended
|
|
366
|
+
module or an inherited ancestor class. Modules are checked for an extended
|
|
367
|
+
module.
|
|
368
|
+
|
|
369
|
+
``` rb
|
|
370
|
+
class InterfaceInteraction < ActiveInteraction::Base
|
|
371
|
+
interface :exception
|
|
372
|
+
|
|
373
|
+
def execute
|
|
374
|
+
exception
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
InterfaceInteraction.run!(exception: Exception)
|
|
379
|
+
# ActiveInteraction::InvalidInteractionError: Exception is not a valid interface
|
|
380
|
+
InterfaceInteraction.run!(exception: NameError) # a subclass of Exception
|
|
381
|
+
# => NameError
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
You can use `:from` to specify a class or module. This would be the equivalent
|
|
385
|
+
of what's above.
|
|
386
|
+
|
|
387
|
+
```rb
|
|
388
|
+
class InterfaceInteraction < ActiveInteraction::Base
|
|
389
|
+
interface :error,
|
|
390
|
+
from: Exception
|
|
391
|
+
|
|
392
|
+
def execute
|
|
393
|
+
error
|
|
394
|
+
end
|
|
395
|
+
end
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
You can also create an anonymous interface on the fly by passing the `methods`
|
|
399
|
+
option.
|
|
358
400
|
|
|
359
401
|
``` rb
|
|
360
402
|
class InterfaceInteraction < ActiveInteraction::Base
|
|
@@ -378,30 +420,10 @@ InterfaceInteraction.run!(serializer: JSON)
|
|
|
378
420
|
# => "{\"is_json\":true}"
|
|
379
421
|
```
|
|
380
422
|
|
|
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
423
|
### Object
|
|
401
424
|
|
|
402
|
-
Object filters allow you to require an instance of a particular class
|
|
403
|
-
|
|
404
|
-
it also works with classes that have mixed modules in with `include`.
|
|
425
|
+
Object filters allow you to require an instance of a particular class or one of
|
|
426
|
+
its subclasses.
|
|
405
427
|
|
|
406
428
|
``` rb
|
|
407
429
|
class Cow
|
|
@@ -438,8 +460,8 @@ object :dolly3,
|
|
|
438
460
|
```
|
|
439
461
|
|
|
440
462
|
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
|
|
442
|
-
not
|
|
463
|
+
you can use the `converter` option. It is only called if the value provided is
|
|
464
|
+
not an instance of the class or one of its subclasses. The `converter` option
|
|
443
465
|
accepts a symbol that specifies a class method on the object class or a proc.
|
|
444
466
|
Both will be passed the value and any errors thrown inside the converter will
|
|
445
467
|
cause the value to be considered invalid. Any returned value that is not the
|
|
@@ -466,13 +488,13 @@ ObjectInteraction.run!(ip_address: 1)
|
|
|
466
488
|
|
|
467
489
|
### Record
|
|
468
490
|
|
|
469
|
-
Record filters allow you to require an instance of a particular class or
|
|
470
|
-
that can be used to locate an instance of the
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
491
|
+
Record filters allow you to require an instance of a particular class (or one
|
|
492
|
+
of its subclasses) or a value that can be used to locate an instance of the
|
|
493
|
+
object. If the value does not match, it will call `find` on the class of the
|
|
494
|
+
record. This is particularly useful when working with ActiveRecord objects.
|
|
495
|
+
Like an object filter, the class is derived from the name passed but can be
|
|
496
|
+
specified with the `class` option. The value given to the `default` option will
|
|
497
|
+
also be found.
|
|
476
498
|
|
|
477
499
|
``` rb
|
|
478
500
|
class RecordInteraction < ActiveInteraction::Base
|
|
@@ -542,9 +564,10 @@ SymbolInteraction.run!(method: :object_id)
|
|
|
542
564
|
### Dates and times
|
|
543
565
|
|
|
544
566
|
Filters that work with dates and times behave similarly. By default, they all
|
|
545
|
-
convert strings into their expected data types using `.parse`.
|
|
546
|
-
`format` option, they will instead
|
|
547
|
-
formats won't work with `DateTime`
|
|
567
|
+
convert strings into their expected data types using `.parse`. Blank strings
|
|
568
|
+
will be treated as `nil`. If you give the `format` option, they will instead
|
|
569
|
+
convert strings using `.strptime`. Note that formats won't work with `DateTime`
|
|
570
|
+
and `Time` filters if a time zone is set.
|
|
548
571
|
|
|
549
572
|
#### Date
|
|
550
573
|
|
|
@@ -618,7 +641,8 @@ time :start,
|
|
|
618
641
|
### Numbers
|
|
619
642
|
|
|
620
643
|
All numeric filters accept numeric input. They will also convert strings using
|
|
621
|
-
the appropriate method from `Kernel` (like `.Float`).
|
|
644
|
+
the appropriate method from `Kernel` (like `.Float`). Blank strings will be
|
|
645
|
+
treated as `nil`.
|
|
622
646
|
|
|
623
647
|
#### Decimal
|
|
624
648
|
|
|
@@ -679,24 +703,27 @@ IntegerInteraction.run!(limit: 10)
|
|
|
679
703
|
```
|
|
680
704
|
|
|
681
705
|
When a `String` is passed into an `integer` input, the value will be coerced.
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
706
|
+
A default base of `10` is used though it may be overridden with the `base` option.
|
|
707
|
+
If a base of `0` is provided, the coercion will respect radix indicators present
|
|
708
|
+
in the string.
|
|
685
709
|
|
|
686
710
|
``` rb
|
|
687
711
|
class IntegerInteraction < ActiveInteraction::Base
|
|
688
|
-
integer :limit1
|
|
689
|
-
integer :limit2
|
|
712
|
+
integer :limit1
|
|
713
|
+
integer :limit2, base: 8
|
|
714
|
+
integer :limit3, base: 0
|
|
690
715
|
|
|
691
716
|
def execute
|
|
692
|
-
[limit1, limit2]
|
|
717
|
+
[limit1, limit2, limit3]
|
|
693
718
|
end
|
|
694
719
|
end
|
|
695
720
|
|
|
696
|
-
IntegerInteraction.run!(limit1:
|
|
697
|
-
# => [
|
|
698
|
-
IntegerInteraction.run!(limit1: "
|
|
699
|
-
#
|
|
721
|
+
IntegerInteraction.run!(limit1: 71, limit2: 71, limit3: 71)
|
|
722
|
+
# => [71, 71, 71]
|
|
723
|
+
IntegerInteraction.run!(limit1: "071", limit2: "071", limit3: "0x71")
|
|
724
|
+
# => [71, 57, 113]
|
|
725
|
+
IntegerInteraction.run!(limit1: "08", limit2: "08", limit3: "08")
|
|
726
|
+
ActiveInteraction::InvalidInteractionError: Limit2 is not a valid integer, Limit3 is not a valid integer
|
|
700
727
|
```
|
|
701
728
|
|
|
702
729
|
## Rails
|
|
@@ -940,10 +967,6 @@ The interaction that updates accounts is more complicated than the others. It
|
|
|
940
967
|
requires an account to update, but the other inputs are optional. If they're
|
|
941
968
|
missing, it'll ignore those attributes. If they're present, it'll update them.
|
|
942
969
|
|
|
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
970
|
``` rb
|
|
948
971
|
class UpdateAccount < ActiveInteraction::Base
|
|
949
972
|
object :account
|
|
@@ -953,14 +976,14 @@ class UpdateAccount < ActiveInteraction::Base
|
|
|
953
976
|
|
|
954
977
|
validates :first_name,
|
|
955
978
|
presence: true,
|
|
956
|
-
|
|
979
|
+
unless: -> { first_name.nil? }
|
|
957
980
|
validates :last_name,
|
|
958
981
|
presence: true,
|
|
959
|
-
|
|
982
|
+
unless: -> { last_name.nil? }
|
|
960
983
|
|
|
961
984
|
def execute
|
|
962
|
-
account.first_name = first_name if first_name?
|
|
963
|
-
account.last_name = last_name if last_name?
|
|
985
|
+
account.first_name = first_name if first_name.present?
|
|
986
|
+
account.last_name = last_name if last_name.present?
|
|
964
987
|
|
|
965
988
|
unless account.save
|
|
966
989
|
errors.merge!(account.errors)
|
|
@@ -1177,9 +1200,6 @@ def execute
|
|
|
1177
1200
|
end
|
|
1178
1201
|
```
|
|
1179
1202
|
|
|
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
1203
|
ActiveInteraction also supports merging errors. This is useful if you want to
|
|
1184
1204
|
delegate validation to some other object. For example, if you have an
|
|
1185
1205
|
interaction that updates a record, you might want that record to validate
|
|
@@ -1375,41 +1395,6 @@ UpdateUser.run!(user: user, birthday: nil)
|
|
|
1375
1395
|
UpdateUser.run!(user: user, birthday: Date.new(2000, 1, 2))
|
|
1376
1396
|
```
|
|
1377
1397
|
|
|
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
1398
|
### Translations
|
|
1414
1399
|
|
|
1415
1400
|
ActiveInteraction is i18n aware out of the box! All you have to do is add
|
|
@@ -1462,8 +1447,8 @@ I18nInteraction.run(name: false).errors.messages[:name]
|
|
|
1462
1447
|
|
|
1463
1448
|
## Credits
|
|
1464
1449
|
|
|
1465
|
-
ActiveInteraction is brought to you by [Aaron Lasseigne][]
|
|
1466
|
-
[Taylor Fausak][] and
|
|
1450
|
+
ActiveInteraction is brought to you by [Aaron Lasseigne][].
|
|
1451
|
+
Along with Aaron, [Taylor Fausak][] helped create and maintain ActiveInteraction but has since moved on.
|
|
1467
1452
|
|
|
1468
1453
|
If you want to contribute to ActiveInteraction, please read
|
|
1469
1454
|
[our contribution guidelines][]. A [complete list of contributors][] is
|
|
@@ -1472,14 +1457,11 @@ available on GitHub.
|
|
|
1472
1457
|
ActiveInteraction is licensed under [the MIT License][].
|
|
1473
1458
|
|
|
1474
1459
|
[activeinteraction]: https://github.com/AaronLasseigne/active_interaction
|
|
1475
|
-
[
|
|
1460
|
+
[API Documentation]: http://rubydoc.info/github/AaronLasseigne/active_interaction
|
|
1476
1461
|
[semantic versioning]: http://semver.org/spec/v2.0.0.html
|
|
1477
1462
|
[GitHub releases]: https://github.com/AaronLasseigne/active_interaction/releases
|
|
1478
|
-
[the announcement post]: http://devblog.orgsync.com/2015/05/06/announcing-active-interaction-2/
|
|
1479
|
-
[active_model-errors_details]: https://github.com/cowbell/active_model-errors_details
|
|
1480
1463
|
[aaron lasseigne]: https://github.com/AaronLasseigne
|
|
1481
1464
|
[taylor fausak]: https://github.com/tfausak
|
|
1482
|
-
[orgsync]: https://github.com/orgsync
|
|
1483
1465
|
[our contribution guidelines]: CONTRIBUTING.md
|
|
1484
1466
|
[complete list of contributors]: https://github.com/AaronLasseigne/active_interaction/graphs/contributors
|
|
1485
1467
|
[the mit license]: LICENSE.md
|
|
@@ -1488,5 +1470,4 @@ ActiveInteraction is licensed under [the MIT License][].
|
|
|
1488
1470
|
[the filters section]: #filters
|
|
1489
1471
|
[the errors section]: #errors
|
|
1490
1472
|
[the optional inputs section]: #optional-inputs
|
|
1491
|
-
[aire]: example
|
|
1492
1473
|
[`with_options`]: http://api.rubyonrails.org/classes/Object.html#method-i-with_options
|