active_interaction 2.2.0 → 3.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ab0b6acaa850b033873f57885ab405bd0617fb1
4
- data.tar.gz: fa8014160f12647a93e6630e740a7caea0b6e866
3
+ metadata.gz: 66bb9089f91627be5b2370b6e68eb216ff3da581
4
+ data.tar.gz: 0f107c34005d354adb1fc2bad3b72776b588b455
5
5
  SHA512:
6
- metadata.gz: 7c3ba3db8d3d3f6886e0badc849f80036d7633bdc2e4cfef8da3fcf07c556167181bd182757f0b0aae8fd9fc8d273b75a3bcf88d320310f5f7bc41ea6f8d0490
7
- data.tar.gz: 9b0588c2945678a31fbf315bf2b44f2168d5dbfad1e4398e2c07a558f91ae0fa66ac15622a3b4b049ee103b863ed290091963098cccc1c35e74f64a361b8ee22
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', '~> 2.2'
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 '~> 2.2'
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.2)
84
- and ActiveModel (3.2 through 4.2).
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
- merge_errors_onto_base(result_or_errors)
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
- add(attribute, error, detail) unless added?(attribute, error, detail)
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
@@ -47,7 +47,7 @@ module ActiveInteraction
47
47
  #
48
48
  # @return [Boolean]
49
49
  def number?
50
- [:integer, :float].include?(type)
50
+ %i[integer float].include?(type)
51
51
  end
52
52
 
53
53
  # Returns `true` if the column is of type :string.
@@ -15,7 +15,7 @@ module ActiveInteraction
15
15
  # interface :anything
16
16
  # @example
17
17
  # interface :serializer,
18
- # methods: [:dump, :load]
18
+ # methods: %i[dump load]
19
19
  end
20
20
 
21
21
  # @private
@@ -6,5 +6,5 @@ module ActiveInteraction
6
6
  # The version number.
7
7
  #
8
8
  # @return [Gem::Version]
9
- VERSION = Gem::Version.new('2.2.0')
9
+ VERSION = Gem::Version.new('3.0.0')
10
10
  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, :y,
22
+ object :x, :z,
23
23
  class: Object,
24
24
  default: nil
25
25
 
26
26
  def execute
27
- compose(AddInteraction, inputs)
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(:y) { rand }
340
+ let(:z) { rand }
341
341
 
342
342
  context 'with valid composition' do
343
343
  before do
344
- inputs.merge!(x: x, y: y)
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 + y
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[:base])
363
- .to match_array ['X is required', 'Y is required']
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) { [:a, :b, :c] }
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) { [:a, :b, :c] }
90
+ let(:names) { %i[a b c] }
91
91
  let(:options) { { a: nil, b: false, c: true } }
92
92
 
93
93
  it 'yields' do
@@ -47,7 +47,7 @@ describe ActiveInteraction::Runnable do
47
47
  end.to_not raise_error
48
48
  end
49
49
 
50
- [:after, :around, :before].each do |type|
50
+ %i[after around before].each do |type|
51
51
  it type do
52
52
  has_run = false
53
53
 
@@ -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] = [:dump, :load] }
11
+ before { options[:methods] = %i[dump load] }
12
12
 
13
13
  describe '#cast' do
14
14
  let(:result) { filter.cast(value, nil) }
@@ -13,7 +13,7 @@ describe InterfaceInteraction do
13
13
  it_behaves_like 'an interaction',
14
14
  :interface,
15
15
  -> { [JSON, YAML].sample },
16
- methods: [:dump, :load]
16
+ methods: %i[dump load]
17
17
 
18
18
  it 'succeeds when given nil' do
19
19
  expect { result }.to_not raise_error
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: 2.2.0
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: 2015-12-18 00:00:00.000000000 Z
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: '3.2'
20
+ version: '4'
21
21
  - - "<"
22
22
  - !ruby/object:Gem::Version
23
- version: '5'
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: '3.2'
30
+ version: '4'
31
31
  - - "<"
32
32
  - !ruby/object:Gem::Version
33
- version: '5'
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: '3.2'
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: '3.2'
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: 1.9.3
295
+ version: '2'
302
296
  required_rubygems_version: !ruby/object:Gem::Requirement
303
297
  requirements:
304
298
  - - ">="