active_interaction 3.2.0 → 3.3.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.
- checksums.yaml +4 -4
- data/README.md +26 -21
- data/lib/active_interaction/base.rb +20 -4
- data/lib/active_interaction/filters/array_filter.rb +1 -1
- data/lib/active_interaction/filters/hash_filter.rb +1 -1
- data/lib/active_interaction/locale/fr.yml +14 -14
- data/lib/active_interaction/modules/input_processor.rb +3 -1
- data/lib/active_interaction/version.rb +1 -1
- data/spec/active_interaction/base_spec.rb +17 -0
- data/spec/active_interaction/modules/input_processor_spec.rb +9 -0
- metadata +16 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bcb762bfdc148c4eeb1e277f07e13c60fb3944d8
|
|
4
|
+
data.tar.gz: 7676378a761abeadec3fecc6e350dd27a7fbdd37
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4abdb88c3887e65abed055d535a49ebf8ff9ccd42fba9798315c3f0cb7646461c60007381867c32a8a5f8b4c87082bd4a8bedd3905e3fec041cd0457daed94e9
|
|
7
|
+
data.tar.gz: b8c6e2b73a547575e9eaa92c3d412044174e3ea1196dd6a868ad17fb657cdbb495a5455f9411ba5bba9f1c76350bf7505ac78f576cae5b8a7080e0e5a751751b
|
data/README.md
CHANGED
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
ActiveInteraction manages application-specific business logic.
|
|
4
4
|
It's an implementation of the command pattern in Ruby.
|
|
5
5
|
|
|
6
|
-
[](https://gemnasium.com/orgsync/active_interaction)
|
|
6
|
+
[](https://rubygems.org/gems/active_interaction)
|
|
7
|
+
[](https://travis-ci.org/orgsync/active_interaction)
|
|
8
|
+
[](https://coveralls.io/r/orgsync/active_interaction)
|
|
9
|
+
[](https://codeclimate.com/github/orgsync/active_interaction)
|
|
10
|
+
[](https://gemnasium.com/orgsync/active_interaction)
|
|
12
11
|
|
|
13
12
|
---
|
|
14
13
|
|
|
@@ -67,23 +66,22 @@ Read more on [the project page][] or check out [the full documentation][].
|
|
|
67
66
|
Add it to your Gemfile:
|
|
68
67
|
|
|
69
68
|
``` rb
|
|
70
|
-
gem 'active_interaction', '~> 3.
|
|
69
|
+
gem 'active_interaction', '~> 3.2'
|
|
71
70
|
```
|
|
72
71
|
|
|
73
72
|
Or install it manually:
|
|
74
73
|
|
|
75
74
|
``` sh
|
|
76
|
-
$ gem install active_interaction --version '~> 3.
|
|
75
|
+
$ gem install active_interaction --version '~> 3.2'
|
|
77
76
|
```
|
|
78
77
|
|
|
79
78
|
This project uses [Semantic Versioning][]. Check out [the change log][] for a
|
|
80
79
|
detailed list of changes. For help upgrading to version 2, please read [the
|
|
81
80
|
announcement post][].
|
|
82
81
|
|
|
83
|
-
ActiveInteraction works with
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
If you want to use ActiveInteraction with Ruby < 2.0.0 or ActiveModel < 4.0.0, use ActiveInteraction < 3.0.0.
|
|
82
|
+
ActiveInteraction works with Ruby 2.0 through 2.3 and ActiveModel 4.0 through
|
|
83
|
+
5.0. If you want to use ActiveInteraction with an older version of Ruby or
|
|
84
|
+
ActiveModel, use ActiveInteraction < 3.0.0.
|
|
87
85
|
|
|
88
86
|
## Basic usage
|
|
89
87
|
|
|
@@ -172,9 +170,9 @@ class SayHello < ActiveInteraction::Base
|
|
|
172
170
|
end
|
|
173
171
|
```
|
|
174
172
|
|
|
175
|
-
When you run this interaction, two things will happen. **First
|
|
176
|
-
will type check your inputs. Then ActiveModel will validate
|
|
177
|
-
those are happy, it will be executed.
|
|
173
|
+
When you run this interaction, two things will happen. **First
|
|
174
|
+
ActiveInteraction will type check your inputs. Then ActiveModel will validate
|
|
175
|
+
them.** If both of those are happy, it will be executed.
|
|
178
176
|
|
|
179
177
|
``` rb
|
|
180
178
|
SayHello.run!(name: nil)
|
|
@@ -189,14 +187,14 @@ SayHello.run!(name: 'Taylor')
|
|
|
189
187
|
|
|
190
188
|
## Filters
|
|
191
189
|
|
|
192
|
-
You can define filters inside an interaction using the appropriate class
|
|
193
|
-
Each method has the same signature:
|
|
190
|
+
You can define filters inside an interaction using the appropriate class
|
|
191
|
+
method. Each method has the same signature:
|
|
194
192
|
|
|
195
193
|
- Some symbolic names. These are the attributes to create.
|
|
196
194
|
|
|
197
195
|
- An optional hash of options. Each filter supports at least these two options:
|
|
198
196
|
|
|
199
|
-
- `default` is the fallback value to use if `nil` is
|
|
197
|
+
- `default` is the fallback value to use if `nil` is given. To make a filter
|
|
200
198
|
optional, set `default: nil`.
|
|
201
199
|
|
|
202
200
|
- `desc` is a human-readable description of the input. This can be useful for
|
|
@@ -218,7 +216,7 @@ array :x, :y, :z,
|
|
|
218
216
|
end
|
|
219
217
|
```
|
|
220
218
|
|
|
221
|
-
In general, filters accept values of the type
|
|
219
|
+
In general, filters accept values of the type they correspond to, plus a few
|
|
222
220
|
alternatives that can be reasonably coerced. Typically the coercions come from
|
|
223
221
|
Rails, so `"1"` can be interpreted as the boolean value `true`, the string
|
|
224
222
|
`"1"`, or the number `1`.
|
|
@@ -875,8 +873,10 @@ end
|
|
|
875
873
|
|
|
876
874
|
We recommend putting your interactions in `app/interactions`. It's also very
|
|
877
875
|
helpful to group them by model. That way you can look in
|
|
878
|
-
`app/interactions/accounts` for all the ways you can interact with accounts.
|
|
879
|
-
|
|
876
|
+
`app/interactions/accounts` for all the ways you can interact with accounts. In
|
|
877
|
+
order to use this structure add
|
|
878
|
+
`config.autoload_paths += Dir.glob("#{config.root}/app/interactions/*")` in
|
|
879
|
+
your `application.rb`
|
|
880
880
|
|
|
881
881
|
```
|
|
882
882
|
- app/
|
|
@@ -1306,6 +1306,11 @@ SayHello.run!(name: 'Taylor')
|
|
|
1306
1306
|
# => "Hello, Taylor!"
|
|
1307
1307
|
```
|
|
1308
1308
|
|
|
1309
|
+
This can be confusing for boolean inputs. If you have some boolean input `foo`,
|
|
1310
|
+
then the actual value of that input is available through `foo`. The associated
|
|
1311
|
+
predicate method, `#foo?`, will tell you if that value is not `nil`. So it will
|
|
1312
|
+
only be `false` if the input is optional and happens to be `nil`.
|
|
1313
|
+
|
|
1309
1314
|
See [the optional inputs section][] for help on determining if an input was
|
|
1310
1315
|
present in the input hash instead of just `nil`.
|
|
1311
1316
|
|
|
@@ -93,7 +93,7 @@ module ActiveInteraction
|
|
|
93
93
|
end
|
|
94
94
|
|
|
95
95
|
# @private
|
|
96
|
-
def method_missing(*args, &block)
|
|
96
|
+
def method_missing(*args, &block) # rubocop:disable Style/MethodMissing
|
|
97
97
|
super do |klass, names, options|
|
|
98
98
|
raise InvalidFilterError, 'missing attribute name' if names.empty?
|
|
99
99
|
|
|
@@ -107,7 +107,9 @@ module ActiveInteraction
|
|
|
107
107
|
# @param name [Symbol]
|
|
108
108
|
# @param options [Hash]
|
|
109
109
|
def add_filter(klass, name, options, &block)
|
|
110
|
-
|
|
110
|
+
if InputProcessor.reserved?(name)
|
|
111
|
+
raise InvalidFilterError, %("#{name}" is a reserved name)
|
|
112
|
+
end
|
|
111
113
|
|
|
112
114
|
initialize_filter(klass.new(name, options, &block))
|
|
113
115
|
end
|
|
@@ -167,8 +169,7 @@ module ActiveInteraction
|
|
|
167
169
|
#
|
|
168
170
|
# @private
|
|
169
171
|
def initialize(inputs = {})
|
|
170
|
-
|
|
171
|
-
|
|
172
|
+
inputs = normalize_inputs!(inputs)
|
|
172
173
|
process_inputs(inputs.symbolize_keys)
|
|
173
174
|
end
|
|
174
175
|
|
|
@@ -232,6 +233,21 @@ module ActiveInteraction
|
|
|
232
233
|
|
|
233
234
|
private
|
|
234
235
|
|
|
236
|
+
# We want to allow both `Hash` objects and `ActionController::Parameters`
|
|
237
|
+
# objects. In Rails < 5, parameters are a subclass of hash and calling
|
|
238
|
+
# `#symbolize_keys` returns the entire hash, not just permitted values. In
|
|
239
|
+
# Rails >= 5, parameters are not a subclass of hash but calling
|
|
240
|
+
# `#to_unsafe_h` returns the entire hash.
|
|
241
|
+
def normalize_inputs!(inputs)
|
|
242
|
+
return inputs if inputs.is_a?(Hash)
|
|
243
|
+
|
|
244
|
+
parameters = 'ActionController::Parameters'
|
|
245
|
+
klass = parameters.safe_constantize
|
|
246
|
+
return inputs.to_unsafe_h if klass && inputs.is_a?(klass)
|
|
247
|
+
|
|
248
|
+
raise ArgumentError, "inputs must be a hash or #{parameters}"
|
|
249
|
+
end
|
|
250
|
+
|
|
235
251
|
# @param inputs [Hash{Symbol => Object}]
|
|
236
252
|
def process_inputs(inputs)
|
|
237
253
|
@_interaction_keys = inputs.keys.to_set & self.class.filters.keys
|
|
@@ -40,7 +40,7 @@ module ActiveInteraction
|
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def method_missing(*args, &block)
|
|
43
|
+
def method_missing(*args, &block) # rubocop:disable Style/MethodMissing
|
|
44
44
|
super(*args) do |klass, names, options|
|
|
45
45
|
raise InvalidFilterError, 'missing attribute name' if names.empty?
|
|
46
46
|
|
|
@@ -3,21 +3,21 @@ fr:
|
|
|
3
3
|
errors:
|
|
4
4
|
messages:
|
|
5
5
|
invalid: est invalide
|
|
6
|
-
invalid_nested:
|
|
7
|
-
invalid_type:
|
|
6
|
+
invalid_nested: contient une valeur imbriquée invalide (%{name} => %{value})
|
|
7
|
+
invalid_type: a un type invalide (%{type})
|
|
8
8
|
missing: est obligatoire
|
|
9
9
|
types:
|
|
10
|
-
array:
|
|
11
|
-
boolean:
|
|
10
|
+
array: tableau
|
|
11
|
+
boolean: booléen
|
|
12
12
|
date: date
|
|
13
|
-
date_time: date
|
|
14
|
-
decimal:
|
|
15
|
-
file:
|
|
16
|
-
float:
|
|
17
|
-
hash:
|
|
18
|
-
integer:
|
|
13
|
+
date_time: date et heure
|
|
14
|
+
decimal: nombre décimal
|
|
15
|
+
file: fichier
|
|
16
|
+
float: nombre à virgule flottante
|
|
17
|
+
hash: tableau associatif
|
|
18
|
+
integer: nombre entier
|
|
19
19
|
interface: interface
|
|
20
|
-
object:
|
|
21
|
-
string:
|
|
22
|
-
symbol:
|
|
23
|
-
time:
|
|
20
|
+
object: objet
|
|
21
|
+
string: chaîne de caractères
|
|
22
|
+
symbol: symbole
|
|
23
|
+
time: temps
|
|
@@ -13,7 +13,9 @@ module ActiveInteraction
|
|
|
13
13
|
private_constant :GROUPED_INPUT_PATTERN
|
|
14
14
|
|
|
15
15
|
def reserved?(name)
|
|
16
|
-
name.to_s.start_with?('_interaction_')
|
|
16
|
+
name.to_s.start_with?('_interaction_') ||
|
|
17
|
+
Base.instance_methods.include?(name) ||
|
|
18
|
+
Base.private_instance_methods.include?(name)
|
|
17
19
|
end
|
|
18
20
|
|
|
19
21
|
def process(inputs)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
|
|
3
3
|
require 'spec_helper'
|
|
4
|
+
require 'action_controller'
|
|
4
5
|
|
|
5
6
|
InteractionWithFilter = Class.new(TestInteraction) do
|
|
6
7
|
float :thing
|
|
@@ -58,6 +59,22 @@ describe ActiveInteraction::Base do
|
|
|
58
59
|
end
|
|
59
60
|
end
|
|
60
61
|
|
|
62
|
+
context 'with non-hash inputs' do
|
|
63
|
+
let(:inputs) { [[:k, :v]] }
|
|
64
|
+
|
|
65
|
+
it 'raises an error' do
|
|
66
|
+
expect { interaction }.to raise_error ArgumentError
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context 'with ActionController::Parameters inputs' do
|
|
71
|
+
let(:inputs) { ActionController::Parameters.new }
|
|
72
|
+
|
|
73
|
+
it 'does not raise an error' do
|
|
74
|
+
expect { interaction }.to_not raise_error
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
61
78
|
context 'with a reader' do
|
|
62
79
|
let(:described_class) do
|
|
63
80
|
Class.new(TestInteraction) do
|
|
@@ -8,6 +8,15 @@ describe ActiveInteraction::InputProcessor do
|
|
|
8
8
|
expect(described_class.reserved?('_interaction_')).to be_truthy
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
it 'returns true for existing instance methods' do
|
|
12
|
+
(
|
|
13
|
+
ActiveInteraction::Base.instance_methods +
|
|
14
|
+
ActiveInteraction::Base.private_instance_methods
|
|
15
|
+
).each do |method|
|
|
16
|
+
expect(described_class.reserved?(method)).to be_truthy
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
11
20
|
it 'returns false for anything else' do
|
|
12
21
|
expect(described_class.reserved?(SecureRandom.hex)).to be_falsey
|
|
13
22
|
end
|
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: 3.
|
|
4
|
+
version: 3.3.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: 2016-
|
|
12
|
+
date: 2016-09-13 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: activemodel
|
|
@@ -51,28 +51,28 @@ dependencies:
|
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '2.
|
|
54
|
+
version: '2.7'
|
|
55
55
|
type: :development
|
|
56
56
|
prerelease: false
|
|
57
57
|
version_requirements: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: '2.
|
|
61
|
+
version: '2.7'
|
|
62
62
|
- !ruby/object:Gem::Dependency
|
|
63
63
|
name: bundler
|
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: '1.
|
|
68
|
+
version: '1.12'
|
|
69
69
|
type: :development
|
|
70
70
|
prerelease: false
|
|
71
71
|
version_requirements: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
73
|
- - "~>"
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '1.
|
|
75
|
+
version: '1.12'
|
|
76
76
|
- !ruby/object:Gem::Dependency
|
|
77
77
|
name: coveralls
|
|
78
78
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -93,70 +93,70 @@ dependencies:
|
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '1.
|
|
96
|
+
version: '1.12'
|
|
97
97
|
type: :development
|
|
98
98
|
prerelease: false
|
|
99
99
|
version_requirements: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
|
101
101
|
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '1.
|
|
103
|
+
version: '1.12'
|
|
104
104
|
- !ruby/object:Gem::Dependency
|
|
105
105
|
name: rake
|
|
106
106
|
requirement: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: '11.
|
|
110
|
+
version: '11.2'
|
|
111
111
|
type: :development
|
|
112
112
|
prerelease: false
|
|
113
113
|
version_requirements: !ruby/object:Gem::Requirement
|
|
114
114
|
requirements:
|
|
115
115
|
- - "~>"
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: '11.
|
|
117
|
+
version: '11.2'
|
|
118
118
|
- !ruby/object:Gem::Dependency
|
|
119
119
|
name: rspec
|
|
120
120
|
requirement: !ruby/object:Gem::Requirement
|
|
121
121
|
requirements:
|
|
122
122
|
- - "~>"
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: '3.
|
|
124
|
+
version: '3.5'
|
|
125
125
|
type: :development
|
|
126
126
|
prerelease: false
|
|
127
127
|
version_requirements: !ruby/object:Gem::Requirement
|
|
128
128
|
requirements:
|
|
129
129
|
- - "~>"
|
|
130
130
|
- !ruby/object:Gem::Version
|
|
131
|
-
version: '3.
|
|
131
|
+
version: '3.5'
|
|
132
132
|
- !ruby/object:Gem::Dependency
|
|
133
133
|
name: rubocop
|
|
134
134
|
requirement: !ruby/object:Gem::Requirement
|
|
135
135
|
requirements:
|
|
136
136
|
- - "~>"
|
|
137
137
|
- !ruby/object:Gem::Version
|
|
138
|
-
version: 0.
|
|
138
|
+
version: 0.42.0
|
|
139
139
|
type: :development
|
|
140
140
|
prerelease: false
|
|
141
141
|
version_requirements: !ruby/object:Gem::Requirement
|
|
142
142
|
requirements:
|
|
143
143
|
- - "~>"
|
|
144
144
|
- !ruby/object:Gem::Version
|
|
145
|
-
version: 0.
|
|
145
|
+
version: 0.42.0
|
|
146
146
|
- !ruby/object:Gem::Dependency
|
|
147
147
|
name: yard
|
|
148
148
|
requirement: !ruby/object:Gem::Requirement
|
|
149
149
|
requirements:
|
|
150
150
|
- - "~>"
|
|
151
151
|
- !ruby/object:Gem::Version
|
|
152
|
-
version: '0.
|
|
152
|
+
version: '0.9'
|
|
153
153
|
type: :development
|
|
154
154
|
prerelease: false
|
|
155
155
|
version_requirements: !ruby/object:Gem::Requirement
|
|
156
156
|
requirements:
|
|
157
157
|
- - "~>"
|
|
158
158
|
- !ruby/object:Gem::Version
|
|
159
|
-
version: '0.
|
|
159
|
+
version: '0.9'
|
|
160
160
|
description: |2
|
|
161
161
|
ActiveInteraction manages application-specific business logic. It is an
|
|
162
162
|
implementation of the command pattern in Ruby.
|
|
@@ -325,4 +325,3 @@ test_files:
|
|
|
325
325
|
- spec/support/concerns.rb
|
|
326
326
|
- spec/support/filters.rb
|
|
327
327
|
- spec/support/interactions.rb
|
|
328
|
-
has_rdoc:
|