active_interaction 2.2.0 → 3.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 +15 -0
- data/README.md +47 -5
- data/lib/active_interaction/backports.rb +0 -26
- data/lib/active_interaction/concerns/runnable.rb +1 -7
- data/lib/active_interaction/errors.rb +21 -1
- data/lib/active_interaction/filter_column.rb +1 -1
- data/lib/active_interaction/filters/interface_filter.rb +1 -1
- data/lib/active_interaction/version.rb +1 -1
- data/spec/active_interaction/base_spec.rb +7 -7
- data/spec/active_interaction/concerns/missable_spec.rb +2 -2
- data/spec/active_interaction/concerns/runnable_spec.rb +1 -1
- data/spec/active_interaction/filters/hash_filter_spec.rb +0 -10
- data/spec/active_interaction/filters/interface_filter_spec.rb +1 -1
- data/spec/active_interaction/integration/interface_interaction_spec.rb +1 -1
- metadata +9 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 66bb9089f91627be5b2370b6e68eb216ff3da581
|
4
|
+
data.tar.gz: 0f107c34005d354adb1fc2bad3b72776b588b455
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d17dab874880c2d8b363e749ef785800bece6d567196937968bd20637a8f7c1df5e653583d0397f11b2934d2c00aba16ada93af8e7b0abda6aa53df07de91463
|
7
|
+
data.tar.gz: 09dbd1ee68e85d8a0b49e492eb2043e75350fb6194385f654cb95fed861bfb63046e53ce7f909f83e0b90ea4097b71e2616d2ba11f6968b864b8004f07906d01
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
# [3.0.0][] (2016-01-13)
|
2
|
+
|
3
|
+
## Changed
|
4
|
+
|
5
|
+
- [#333][]: Copy symbolic errors when using `compose`.
|
6
|
+
|
7
|
+
## Removed
|
8
|
+
|
9
|
+
- [#344][]: Support for Ruby 1.9.3.
|
10
|
+
- [#346][]: Support for ActiveModel 3.2.
|
11
|
+
|
1
12
|
# [2.2.0][] (2015-12-18)
|
2
13
|
|
3
14
|
## Added
|
@@ -493,6 +504,7 @@ For help upgrading to version 2, please read [the announcement post][].
|
|
493
504
|
|
494
505
|
- Initial release.
|
495
506
|
|
507
|
+
[3.0.0]: https://github.com/orgsync/active_interaction/compare/v2.2.0...v3.0.0
|
496
508
|
[2.2.0]: https://github.com/orgsync/active_interaction/compare/v2.1.5...v2.2.0
|
497
509
|
[2.1.5]: https://github.com/orgsync/active_interaction/compare/v2.1.4...v2.1.5
|
498
510
|
[2.1.4]: https://github.com/orgsync/active_interaction/compare/v2.1.3...v2.1.4
|
@@ -644,6 +656,9 @@ For help upgrading to version 2, please read [the announcement post][].
|
|
644
656
|
[#320]: https://github.com/orgsync/active_interaction/issues/320
|
645
657
|
[#330]: https://github.com/orgsync/active_interaction/pull/330
|
646
658
|
[#332]: https://github.com/orgsync/active_interaction/pull/332
|
659
|
+
[#333]: https://github.com/orgsync/active_interaction/pull/333
|
647
660
|
[#336]: https://github.com/orgsync/active_interaction/pull/336
|
661
|
+
[#344]: https://github.com/orgsync/active_interaction/pull/344
|
662
|
+
[#346]: https://github.com/orgsync/active_interaction/pull/346
|
648
663
|
|
649
664
|
[the announcement post]: http://devblog.orgsync.com/2015/05/06/announcing-active-interaction-2/
|
data/README.md
CHANGED
@@ -67,21 +67,23 @@ Read more on [the project page][] or check out [the full documentation][].
|
|
67
67
|
Add it to your Gemfile:
|
68
68
|
|
69
69
|
``` rb
|
70
|
-
gem 'active_interaction', '~>
|
70
|
+
gem 'active_interaction', '~> 3.0'
|
71
71
|
```
|
72
72
|
|
73
73
|
Or install it manually:
|
74
74
|
|
75
75
|
``` sh
|
76
|
-
$ gem install active_interaction --version '~>
|
76
|
+
$ gem install active_interaction --version '~> 3.0'
|
77
77
|
```
|
78
78
|
|
79
79
|
This project uses [Semantic Versioning][]. Check out [the change log][] for a
|
80
80
|
detailed list of changes. For help upgrading to version 2, please read [the
|
81
81
|
announcement post][].
|
82
82
|
|
83
|
-
ActiveInteraction works with all supported versions of Ruby (2.0 through 2.
|
84
|
-
and ActiveModel (
|
83
|
+
ActiveInteraction works with all supported versions of Ruby (2.0 through 2.3)
|
84
|
+
and ActiveModel (4.0 through 4.2).
|
85
|
+
|
86
|
+
If you want to use ActiveInteraction with Ruby < 2.0.0 or ActiveModel < 4.0.0, use ActiveInteraction < 3.0.0.
|
85
87
|
|
86
88
|
## Basic usage
|
87
89
|
|
@@ -873,7 +875,7 @@ end
|
|
873
875
|
|
874
876
|
We recommend putting your interactions in `app/interactions`. It's also very
|
875
877
|
helpful to group them by model. That way you can look in
|
876
|
-
`app/interactions/accounts` for all the ways you can interact with accounts.
|
878
|
+
`app/interactions/accounts` for all the ways you can interact with accounts.
|
877
879
|
In order to use this structure add `config.autoload_paths += Dir.glob("#{config.root}/app/interactions/*")` in your `application.rb`
|
878
880
|
|
879
881
|
```
|
@@ -981,6 +983,9 @@ class AddAndDouble < ActiveInteraction::Base
|
|
981
983
|
end
|
982
984
|
```
|
983
985
|
|
986
|
+
Note that errors in composed interactions have a few tricky cases. See [the
|
987
|
+
errors section][] for more information about them.
|
988
|
+
|
984
989
|
### Defaults
|
985
990
|
|
986
991
|
The default value for an input can take on many different forms. Setting the
|
@@ -1100,6 +1105,42 @@ class UpdateThing < ActiveInteraction::Base
|
|
1100
1105
|
end
|
1101
1106
|
```
|
1102
1107
|
|
1108
|
+
When a composed interaction fails, its errors are merged onto the caller. This
|
1109
|
+
generally produces good error messages, but there are a few cases to look out
|
1110
|
+
for.
|
1111
|
+
|
1112
|
+
``` rb
|
1113
|
+
class Inner < ActiveInteraction::Base
|
1114
|
+
boolean :x, :y
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
class Outer < ActiveInteraction::Base
|
1118
|
+
string :x
|
1119
|
+
boolean :z, default: nil
|
1120
|
+
|
1121
|
+
def execute
|
1122
|
+
compose(Inner, x: x, y: z)
|
1123
|
+
end
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
outcome = Outer.run(x: 'yes')
|
1127
|
+
outcome.errors.details
|
1128
|
+
# => { :x => [{ :error => :invalid_type, :type => "boolean" }],
|
1129
|
+
# :base => [{ :error => "Y is required" }] }
|
1130
|
+
outcome.errors.full_messages.join(' and ')
|
1131
|
+
# => "X is not a valid boolean and Y is required"
|
1132
|
+
```
|
1133
|
+
|
1134
|
+
Since both interactions have an input called `x`, the inner error for that
|
1135
|
+
input is moved to the `x` error on the outer interaction. This results in a
|
1136
|
+
misleading error that claims the input `x` is not a valid boolean even though
|
1137
|
+
it's a string on the outer interaction.
|
1138
|
+
|
1139
|
+
Since only the inner interaction has an input called `y`, the inner error for
|
1140
|
+
that input is moved to the `base` error on the outer interaction. This results
|
1141
|
+
in a confusing error that claims the input `y` is required even though it's not
|
1142
|
+
present on the outer interaction.
|
1143
|
+
|
1103
1144
|
### Forms
|
1104
1145
|
|
1105
1146
|
The outcome returned by `.run` can be used in forms as though it were an
|
@@ -1348,6 +1389,7 @@ ActiveInteraction is licensed under [the MIT License][].
|
|
1348
1389
|
[formtastic]: https://rubygems.org/gems/formtastic
|
1349
1390
|
[simple_form]: https://rubygems.org/gems/simple_form
|
1350
1391
|
[the filters section]: #filters
|
1392
|
+
[the errors section]: #errors
|
1351
1393
|
[the optional inputs section]: #optional-inputs
|
1352
1394
|
[aire]: example
|
1353
1395
|
[`with_options`]: http://api.rubyonrails.org/classes/Object.html#method-i-with_options
|
@@ -4,22 +4,7 @@
|
|
4
4
|
require 'active_support/core_ext'
|
5
5
|
|
6
6
|
module ActiveInteraction
|
7
|
-
class GroupedInput # rubocop:disable Style/Documentation
|
8
|
-
# Required for Ruby <= 1.9.3.
|
9
|
-
def [](name)
|
10
|
-
send(name)
|
11
|
-
end unless method_defined?(:[])
|
12
|
-
|
13
|
-
# Required for Ruby <= 1.9.3.
|
14
|
-
def []=(name, value)
|
15
|
-
send("#{name}=", value)
|
16
|
-
end unless method_defined?(:[]=)
|
17
|
-
end
|
18
|
-
|
19
7
|
class Errors # rubocop:disable Style/Documentation
|
20
|
-
# Required for Rails < 3.2.13.
|
21
|
-
protected :initialize_dup
|
22
|
-
|
23
8
|
# Required for Rails < 5.
|
24
9
|
#
|
25
10
|
# Extracted from active_model-errors_details 1.2.0. Modified to add support
|
@@ -67,15 +52,4 @@ module ActiveInteraction
|
|
67
52
|
end
|
68
53
|
include Details unless method_defined?(:details)
|
69
54
|
end
|
70
|
-
|
71
|
-
class HashFilter # rubocop:disable Style/Documentation
|
72
|
-
# Required for Rails < 4.0.0.
|
73
|
-
def self.transform_keys(hash, &block)
|
74
|
-
return hash.transform_keys(&block) if hash.respond_to?(:transform_keys)
|
75
|
-
|
76
|
-
result = {}
|
77
|
-
hash.each_key { |key| result[block.call(key)] = hash[key] }
|
78
|
-
result
|
79
|
-
end
|
80
|
-
end
|
81
55
|
end
|
@@ -80,18 +80,12 @@ module ActiveInteraction
|
|
80
80
|
|
81
81
|
self.result =
|
82
82
|
if result_or_errors.is_a?(ActiveInteraction::Errors)
|
83
|
-
|
83
|
+
errors.merge!(result_or_errors)
|
84
84
|
else
|
85
85
|
result_or_errors
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
def merge_errors_onto_base(new_errors)
|
90
|
-
new_errors.full_messages.each do |message|
|
91
|
-
errors.add(:base, message) unless errors.added?(:base, message)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
89
|
# @return [Object]
|
96
90
|
#
|
97
91
|
# @raise [InvalidInteractionError] If there are validation errors.
|
@@ -97,6 +97,10 @@ module ActiveInteraction
|
|
97
97
|
def merge_messages!(other)
|
98
98
|
other.messages.each do |attribute, messages|
|
99
99
|
messages.each do |message|
|
100
|
+
unless attribute?(attribute)
|
101
|
+
message = full_message(attribute, message)
|
102
|
+
attribute = :base
|
103
|
+
end
|
100
104
|
add(attribute, message) unless added?(attribute, message)
|
101
105
|
end
|
102
106
|
end
|
@@ -107,9 +111,25 @@ module ActiveInteraction
|
|
107
111
|
details.each do |detail|
|
108
112
|
detail = detail.dup
|
109
113
|
error = detail.delete(:error)
|
110
|
-
|
114
|
+
|
115
|
+
merge_detail!(other, attribute, detail, error)
|
111
116
|
end
|
112
117
|
end
|
113
118
|
end
|
119
|
+
|
120
|
+
def merge_detail!(other, attribute, detail, error)
|
121
|
+
if attribute?(attribute)
|
122
|
+
add(attribute, error, detail) unless added?(attribute, error, detail)
|
123
|
+
else
|
124
|
+
message = full_message(
|
125
|
+
attribute, other.generate_message(attribute, error))
|
126
|
+
attribute = :base
|
127
|
+
add(attribute, message) unless added?(attribute, message)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def attribute?(attribute)
|
132
|
+
@base.respond_to?(attribute)
|
133
|
+
end
|
114
134
|
end
|
115
135
|
end
|
@@ -19,12 +19,12 @@ AddInteraction = Class.new(TestInteraction) do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
InterruptInteraction = Class.new(TestInteraction) do
|
22
|
-
object :x, :
|
22
|
+
object :x, :z,
|
23
23
|
class: Object,
|
24
24
|
default: nil
|
25
25
|
|
26
26
|
def execute
|
27
|
-
compose(AddInteraction,
|
27
|
+
compose(AddInteraction, x: x, y: z)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -337,11 +337,11 @@ describe ActiveInteraction::Base do
|
|
337
337
|
describe '#compose' do
|
338
338
|
let(:described_class) { InterruptInteraction }
|
339
339
|
let(:x) { rand }
|
340
|
-
let(:
|
340
|
+
let(:z) { rand }
|
341
341
|
|
342
342
|
context 'with valid composition' do
|
343
343
|
before do
|
344
|
-
inputs.merge!(x: x,
|
344
|
+
inputs.merge!(x: x, z: z)
|
345
345
|
end
|
346
346
|
|
347
347
|
it 'is valid' do
|
@@ -349,7 +349,7 @@ describe ActiveInteraction::Base do
|
|
349
349
|
end
|
350
350
|
|
351
351
|
it 'returns the sum' do
|
352
|
-
expect(result).to eql x +
|
352
|
+
expect(result).to eql x + z
|
353
353
|
end
|
354
354
|
end
|
355
355
|
|
@@ -359,8 +359,8 @@ describe ActiveInteraction::Base do
|
|
359
359
|
end
|
360
360
|
|
361
361
|
it 'has the correct errors' do
|
362
|
-
expect(outcome.errors
|
363
|
-
.to
|
362
|
+
expect(outcome.errors.details)
|
363
|
+
.to eql(x: [{ error: :missing }], base: [{ error: 'Y is required' }])
|
364
364
|
end
|
365
365
|
end
|
366
366
|
end
|
@@ -67,7 +67,7 @@ describe ActiveInteraction::Missable do
|
|
67
67
|
end
|
68
68
|
|
69
69
|
context 'with names' do
|
70
|
-
let(:names) { [
|
70
|
+
let(:names) { %i[a b c] }
|
71
71
|
|
72
72
|
it 'yields' do
|
73
73
|
expect do |b|
|
@@ -87,7 +87,7 @@ describe ActiveInteraction::Missable do
|
|
87
87
|
end
|
88
88
|
|
89
89
|
context 'with names & options' do
|
90
|
-
let(:names) { [
|
90
|
+
let(:names) { %i[a b c] }
|
91
91
|
let(:options) { { a: nil, b: false, c: true } }
|
92
92
|
|
93
93
|
it 'yields' do
|
@@ -6,16 +6,6 @@ describe ActiveInteraction::HashFilter, :filter do
|
|
6
6
|
include_context 'filters'
|
7
7
|
it_behaves_like 'a filter'
|
8
8
|
|
9
|
-
context 'backports' do
|
10
|
-
describe '.transform_keys' do
|
11
|
-
it 'transforms keys' do
|
12
|
-
original = { 'key' => 'value' }
|
13
|
-
transformed = described_class.transform_keys(original, &:to_sym)
|
14
|
-
expect(transformed).to eql(key: 'value')
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
9
|
context 'with a nested nameless filter' do
|
20
10
|
let(:block) { proc { hash } }
|
21
11
|
|
@@ -8,7 +8,7 @@ describe ActiveInteraction::InterfaceFilter, :filter do
|
|
8
8
|
include_context 'filters'
|
9
9
|
it_behaves_like 'a filter'
|
10
10
|
|
11
|
-
before { options[:methods] = [
|
11
|
+
before { options[:methods] = %i[dump load] }
|
12
12
|
|
13
13
|
describe '#cast' do
|
14
14
|
let(:result) { filter.cast(value, nil) }
|
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:
|
4
|
+
version: 3.0.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:
|
12
|
+
date: 2016-01-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
@@ -17,40 +17,34 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '4'
|
21
21
|
- - "<"
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: '
|
23
|
+
version: '6'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
28
|
- - ">="
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version: '
|
30
|
+
version: '4'
|
31
31
|
- - "<"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '6'
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: actionpack
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
41
|
-
- - "<"
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '5'
|
40
|
+
version: '0'
|
44
41
|
type: :development
|
45
42
|
prerelease: false
|
46
43
|
version_requirements: !ruby/object:Gem::Requirement
|
47
44
|
requirements:
|
48
45
|
- - ">="
|
49
46
|
- !ruby/object:Gem::Version
|
50
|
-
version: '
|
51
|
-
- - "<"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '5'
|
47
|
+
version: '0'
|
54
48
|
- !ruby/object:Gem::Dependency
|
55
49
|
name: benchmark-ips
|
56
50
|
requirement: !ruby/object:Gem::Requirement
|
@@ -298,7 +292,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
298
292
|
requirements:
|
299
293
|
- - ">="
|
300
294
|
- !ruby/object:Gem::Version
|
301
|
-
version:
|
295
|
+
version: '2'
|
302
296
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
303
297
|
requirements:
|
304
298
|
- - ">="
|