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 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
  - - ">="