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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29e4b39bc19f6cbe5c7480b4bf43498e7d3013e5
4
- data.tar.gz: 4e705bc6abe8355b03c3c7818869aec7797bd4d4
3
+ metadata.gz: bcb762bfdc148c4eeb1e277f07e13c60fb3944d8
4
+ data.tar.gz: 7676378a761abeadec3fecc6e350dd27a7fbdd37
5
5
  SHA512:
6
- metadata.gz: ea5472b8cbf5ad563b43e0e8b5cd97da6a9c7284bd3c5134271ef7ed92bc7342b3c5e1f5b5e48805bac7f9dc4c8ca977798704cd914f4488f7759630e25b5ac2
7
- data.tar.gz: 046f316bd5cf3962bd083a6afb4876bbf2c73c7a78b7ad47fb8aefa2f7d38301a4c198711c1bcef2c300e5e0c2b2989f50790bd79c09f421d3b68c5587a625ec
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
- [![Version](https://img.shields.io/gem/v/active_interaction.svg?label=version)](https://rubygems.org/gems/active_interaction)
7
- [![Build](https://img.shields.io/travis/orgsync/active_interaction/master.svg?label=build)](https://travis-ci.org/orgsync/active_interaction)
8
- [![Coverage](https://img.shields.io/coveralls/orgsync/active_interaction/master.svg?label=coverage)](https://coveralls.io/r/orgsync/active_interaction)
9
- [![Climate](https://img.shields.io/codeclimate/github/orgsync/active_interaction.svg?label=climate)](https://codeclimate.com/github/orgsync/active_interaction)
10
- [![Grade](https://img.shields.io/badge/grade-A-brightgreen.svg)](http://www.libgrader.com/libraries/ruby/active_interaction)
11
- [![Dependencies](https://img.shields.io/gemnasium/orgsync/active_interaction.svg?label=dependencies)](https://gemnasium.com/orgsync/active_interaction)
6
+ [![Version](https://badge.fury.io/rb/active_interaction.svg)](https://rubygems.org/gems/active_interaction)
7
+ [![Build](https://travis-ci.org/orgsync/active_interaction.svg?branch=master)](https://travis-ci.org/orgsync/active_interaction)
8
+ [![Coverage](https://coveralls.io/repos/github/orgsync/active_interaction/badge.svg?branch=master)](https://coveralls.io/r/orgsync/active_interaction)
9
+ [![Climate](https://codeclimate.com/github/orgsync/active_interaction/badges/gpa.svg)](https://codeclimate.com/github/orgsync/active_interaction)
10
+ [![Dependencies](https://gemnasium.com/orgsync/active_interaction.svg)](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.0'
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.0'
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 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.
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 ActiveInteraction
176
- will type check your inputs. Then ActiveModel will validate them.** If both of
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 method.
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 give. To make a filter
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 the correspond to, plus a few
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
- In order to use this structure add `config.autoload_paths += Dir.glob("#{config.root}/app/interactions/*")` in your `application.rb`
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
- raise InvalidFilterError, name.inspect if InputProcessor.reserved?(name)
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
- raise ArgumentError, 'inputs must be a hash' unless inputs.is_a?(Hash)
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(*, &block)
43
+ def method_missing(*, &block) # rubocop:disable Style/MethodMissing
44
44
  super do |klass, names, options|
45
45
  filter = klass.new(name.to_s.singularize.to_sym, options, &block)
46
46
 
@@ -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: possède une nested value invalide (%{name} => %{value})
7
- invalid_type: n'est pas un %{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: array
11
- boolean: boolean
10
+ array: tableau
11
+ boolean: booléen
12
12
  date: date
13
- date_time: date time
14
- decimal: decimal
15
- file: file
16
- float: float
17
- hash: hash
18
- integer: 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: object
21
- string: string
22
- symbol: symbol
23
- time: 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)
@@ -6,5 +6,5 @@ module ActiveInteraction
6
6
  # The version number.
7
7
  #
8
8
  # @return [Gem::Version]
9
- VERSION = Gem::Version.new('3.2.0')
9
+ VERSION = Gem::Version.new('3.3.0')
10
10
  end
@@ -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.2.0
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-06-07 00:00:00.000000000 Z
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.3'
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.3'
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.10'
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.10'
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.9'
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.9'
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.1'
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.1'
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.4'
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.4'
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.40.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.40.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.8'
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.8'
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: