active_interaction 1.2.5 → 1.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: 00f91c5498e12a8463f75e69ddc0b07f8b5b851e
4
- data.tar.gz: 8336e72d5e12d0a793d3c7e188ab3eafb031df07
3
+ metadata.gz: 20cc4b1b768b7f7dddca393b9554a664bb23010a
4
+ data.tar.gz: c746e003137672689025a54a9245330527088366
5
5
  SHA512:
6
- metadata.gz: 47efce81ccf4286b2906b5d79d438f6f69fc6ff76aecfb975544fb64599350d320c1728b9e43fde6ef59f976c95d577676d6b9cea8614eb8603b1b95e5f6c8ea
7
- data.tar.gz: 2593157f8acc004d26a92b5c69fafb2034fd03abc6717034d34fcc0b34a69acf8f5e629716c905702d17421b815ab7152c8fa18ceb41491243afb1c4d4377d8c
6
+ metadata.gz: 678d8066fa76930180a241ab069617a46d083ac2ca558a4cfee8cb4e6a76131e907ed486ddbd898be89d4f513c74a5799169ba556d24240deb9ad005748c7bcd
7
+ data.tar.gz: ac3d346048c4744d9b2ca25f91b2f719d0b3fcec609671feaf94353e00d4717c147c6e9b47a669cf37d39d327b8c9352e4ac6f9f78cd8d3106235c44e5ede6d2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # [Master][]
2
2
 
3
+ # [1.3.0][] (2014-08-15)
4
+
5
+ ## Added
6
+
7
+ - [#178][]: Add an interface filter.
8
+ - [#196][]: Add a `type_check` callback that happens before the `validation`
9
+ callback.
10
+
3
11
  # [1.2.5][] (2014-08-15)
4
12
 
5
13
  ## Fixed
@@ -338,7 +346,8 @@
338
346
 
339
347
  - Initial release.
340
348
 
341
- [master]: https://github.com/orgsync/active_interaction/compare/v1.2.5...master
349
+ [master]: https://github.com/orgsync/active_interaction/compare/v1.3.0...master
350
+ [1.3.0]: https://github.com/orgsync/active_interaction/compare/v1.2.5...v1.3.0
342
351
  [1.2.5]: https://github.com/orgsync/active_interaction/compare/v1.2.4...v1.2.5
343
352
  [1.2.4]: https://github.com/orgsync/active_interaction/compare/v1.2.3...v1.2.4
344
353
  [1.2.3]: https://github.com/orgsync/active_interaction/compare/v1.2.2...v1.2.3
@@ -438,8 +447,10 @@
438
447
  [#173]: https://github.com/orgsync/active_interaction/issues/173
439
448
  [#174]: https://github.com/orgsync/active_interaction/issues/174
440
449
  [#175]: https://github.com/orgsync/active_interaction/issues/175
450
+ [#178]: https://github.com/orgsync/active_interaction/issues/178
441
451
  [#179]: https://github.com/orgsync/active_interaction/issues/179
442
452
  [#192]: https://github.com/orgsync/active_interaction/issues/192
453
+ [#196]: https://github.com/orgsync/active_interaction/issues/196
443
454
  [#201]: https://github.com/orgsync/active_interaction/issues/201
444
455
  [#203]: https://github.com/orgsync/active_interaction/issues/203
445
456
  [#206]: https://github.com/orgsync/active_interaction/issues/206
data/README.md CHANGED
@@ -25,7 +25,7 @@ This project uses [semantic versioning][13].
25
25
  Add it to your Gemfile:
26
26
 
27
27
  ```ruby
28
- gem 'active_interaction', '~> 1.2'
28
+ gem 'active_interaction', '~> 1.3'
29
29
  ```
30
30
 
31
31
  And then execute:
@@ -30,6 +30,7 @@ require 'active_interaction/filters/file_filter'
30
30
  require 'active_interaction/filters/float_filter'
31
31
  require 'active_interaction/filters/hash_filter'
32
32
  require 'active_interaction/filters/integer_filter'
33
+ require 'active_interaction/filters/interface_filter'
33
34
  require 'active_interaction/filters/model_filter'
34
35
  require 'active_interaction/filters/string_filter'
35
36
  require 'active_interaction/filters/symbol_filter'
@@ -49,5 +50,5 @@ I18n.load_path += Dir[File.expand_path(
49
50
  #
50
51
  # @since 1.0.0
51
52
  #
52
- # @version 1.2.5
53
+ # @version 1.3.0
53
54
  module ActiveInteraction end
@@ -31,7 +31,7 @@ module ActiveInteraction
31
31
  include ActiveModelable
32
32
  include Runnable
33
33
 
34
- validate :input_errors
34
+ define_callbacks :type_check
35
35
 
36
36
  class << self
37
37
  include Hashable
@@ -235,6 +235,14 @@ module ActiveInteraction
235
235
  end
236
236
  end
237
237
 
238
+ protected
239
+
240
+ def run_validations!
241
+ type_check
242
+
243
+ super if errors.empty?
244
+ end
245
+
238
246
  private
239
247
 
240
248
  # @param inputs [Hash{Symbol => Object}]
@@ -257,16 +265,16 @@ module ActiveInteraction
257
265
  begin
258
266
  public_send("#{name}=", filter.clean(inputs[name]))
259
267
  rescue InvalidValueError, MissingValueError, InvalidNestedValueError
260
- # Validators (#input_errors) will add errors if appropriate.
268
+ # #type_check will add errors if appropriate.
261
269
  end
262
270
  end
263
271
  end
264
272
 
265
- # @!group Validations
266
-
267
- def input_errors
268
- Validation.validate(self.class.filters, inputs).each do |error|
269
- errors.add_sym(*error)
273
+ def type_check
274
+ run_callbacks(:type_check) do
275
+ Validation.validate(self.class.filters, inputs).each do |error|
276
+ errors.add_sym(*error)
277
+ end
270
278
  end
271
279
  end
272
280
  end
@@ -0,0 +1,44 @@
1
+ # coding: utf-8
2
+
3
+ module ActiveInteraction
4
+ class Base
5
+ # @!method self.interface(*attributes, options = {})
6
+ # Creates accessors for the attributes and ensures that values passed to
7
+ # the attributes implement an interface.
8
+ #
9
+ # @!macro filter_method_params
10
+ # @option options [Array<Symbol>] :methods ([]) the methods that objects
11
+ # conforming to this interface should respond to
12
+ #
13
+ # @example
14
+ # interface :anything
15
+ # @example
16
+ # interface :serializer,
17
+ # methods: [:dump, :load]
18
+ end
19
+
20
+ # @private
21
+ class InterfaceFilter < Filter
22
+ register :interface
23
+
24
+ def cast(value)
25
+ matches?(value) ? value : super
26
+ end
27
+
28
+ private
29
+
30
+ # @param object [Object]
31
+ #
32
+ # @return [Boolean]
33
+ def matches?(object)
34
+ methods.all? { |method| object.respond_to?(method) }
35
+ rescue NoMethodError
36
+ false
37
+ end
38
+
39
+ # @return [Array<Symbol>]
40
+ def methods
41
+ options.fetch(:methods, [])
42
+ end
43
+ end
44
+ end
@@ -16,6 +16,7 @@ en:
16
16
  float: float
17
17
  hash: hash
18
18
  integer: integer
19
+ interface: interface
19
20
  model: model
20
21
  string: string
21
22
  symbol: symbol
@@ -5,5 +5,5 @@ module ActiveInteraction
5
5
  # The version number.
6
6
  #
7
7
  # @return [Gem::Version]
8
- VERSION = Gem::Version.new('1.2.5')
8
+ VERSION = Gem::Version.new('1.3.0')
9
9
  end
@@ -531,4 +531,76 @@ describe ActiveInteraction::Base do
531
531
  include_examples 'import_filters examples', [:x], [:x]
532
532
  end
533
533
  end
534
+
535
+ context 'callbacks' do
536
+ let(:described_class) { Class.new(TestInteraction) }
537
+
538
+ %w[type_check validate execute].each do |name|
539
+ %w[before after around].map(&:to_sym).each do |type|
540
+ it "runs the #{type} #{name} callback" do
541
+ called = false
542
+ described_class.set_callback(name, type) { called = true }
543
+ outcome
544
+ expect(called).to be_truthy
545
+ end
546
+ end
547
+ end
548
+
549
+ context 'with errors during type_check' do
550
+ before do
551
+ described_class.set_callback(:type_check, :before) do
552
+ errors.add(:base)
553
+ end
554
+ end
555
+
556
+ it 'is invalid' do
557
+ expect(outcome).to be_invalid
558
+ end
559
+
560
+ it 'does not run validate callbacks' do
561
+ called = false
562
+ described_class.set_callback(:validate, :before) { called = true }
563
+ outcome
564
+ expect(called).to be_falsey
565
+ end
566
+
567
+ it 'does not run execute callbacks' do
568
+ called = false
569
+ described_class.set_callback(:execute, :before) { called = true }
570
+ outcome
571
+ expect(called).to be_falsey
572
+ end
573
+ end
574
+
575
+ context 'with errors during validate' do
576
+ before do
577
+ described_class.set_callback(:validate, :before) do
578
+ errors.add(:base)
579
+ end
580
+ end
581
+
582
+ it 'is invalid' do
583
+ expect(outcome).to be_invalid
584
+ end
585
+
586
+ it 'does not run execute callbacks' do
587
+ called = false
588
+ described_class.set_callback(:execute, :before) { called = true }
589
+ outcome
590
+ expect(called).to be_falsey
591
+ end
592
+ end
593
+
594
+ context 'with errors during execute' do
595
+ before do
596
+ described_class.set_callback(:execute, :before) do
597
+ errors.add(:base)
598
+ end
599
+ end
600
+
601
+ it 'is invalid' do
602
+ expect(outcome).to be_invalid
603
+ end
604
+ end
605
+ end
534
606
  end
@@ -0,0 +1,46 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'json'
5
+ require 'yaml'
6
+
7
+ describe ActiveInteraction::InterfaceFilter, :filter do
8
+ include_context 'filters'
9
+ it_behaves_like 'a filter'
10
+
11
+ before { options[:methods] = [:dump, :load] }
12
+
13
+ describe '#cast' do
14
+ let(:result) { filter.cast(value) }
15
+
16
+ context 'with an Object' do
17
+ let(:value) { Object.new }
18
+
19
+ it 'raises an error' do
20
+ expect { result }.to raise_error ActiveInteraction::InvalidValueError
21
+ end
22
+ end
23
+
24
+ context 'with JSON' do
25
+ let(:value) { JSON }
26
+
27
+ it 'returns an Array' do
28
+ expect(result).to eql value
29
+ end
30
+ end
31
+
32
+ context 'with YAML' do
33
+ let(:value) { YAML }
34
+
35
+ it 'returns an Hash' do
36
+ expect(result).to eql value
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#database_column_type' do
42
+ it 'returns :string' do
43
+ expect(filter.database_column_type).to eql :string
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,12 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+ require 'json'
5
+ require 'yaml'
6
+
7
+ describe 'InterfaceInteraction' do
8
+ it_behaves_like 'an interaction',
9
+ :interface,
10
+ -> { [JSON, YAML].sample },
11
+ methods: [:dump, :load]
12
+ 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: 1.2.5
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Lasseigne
@@ -187,6 +187,7 @@ files:
187
187
  - lib/active_interaction/filters/float_filter.rb
188
188
  - lib/active_interaction/filters/hash_filter.rb
189
189
  - lib/active_interaction/filters/integer_filter.rb
190
+ - lib/active_interaction/filters/interface_filter.rb
190
191
  - lib/active_interaction/filters/model_filter.rb
191
192
  - lib/active_interaction/filters/string_filter.rb
192
193
  - lib/active_interaction/filters/symbol_filter.rb
@@ -217,6 +218,7 @@ files:
217
218
  - spec/active_interaction/filters/float_filter_spec.rb
218
219
  - spec/active_interaction/filters/hash_filter_spec.rb
219
220
  - spec/active_interaction/filters/integer_filter_spec.rb
221
+ - spec/active_interaction/filters/interface_filter_spec.rb
220
222
  - spec/active_interaction/filters/model_filter_spec.rb
221
223
  - spec/active_interaction/filters/string_filter_spec.rb
222
224
  - spec/active_interaction/filters/symbol_filter_spec.rb
@@ -231,6 +233,7 @@ files:
231
233
  - spec/active_interaction/integration/float_interaction_spec.rb
232
234
  - spec/active_interaction/integration/hash_interaction_spec.rb
233
235
  - spec/active_interaction/integration/integer_interaction_spec.rb
236
+ - spec/active_interaction/integration/interface_interaction_spec.rb
234
237
  - spec/active_interaction/integration/model_interaction_spec.rb
235
238
  - spec/active_interaction/integration/string_interaction_spec.rb
236
239
  - spec/active_interaction/integration/symbol_interaction_spec.rb
@@ -291,6 +294,7 @@ test_files:
291
294
  - spec/active_interaction/filters/float_filter_spec.rb
292
295
  - spec/active_interaction/filters/hash_filter_spec.rb
293
296
  - spec/active_interaction/filters/integer_filter_spec.rb
297
+ - spec/active_interaction/filters/interface_filter_spec.rb
294
298
  - spec/active_interaction/filters/model_filter_spec.rb
295
299
  - spec/active_interaction/filters/string_filter_spec.rb
296
300
  - spec/active_interaction/filters/symbol_filter_spec.rb
@@ -305,6 +309,7 @@ test_files:
305
309
  - spec/active_interaction/integration/float_interaction_spec.rb
306
310
  - spec/active_interaction/integration/hash_interaction_spec.rb
307
311
  - spec/active_interaction/integration/integer_interaction_spec.rb
312
+ - spec/active_interaction/integration/interface_interaction_spec.rb
308
313
  - spec/active_interaction/integration/model_interaction_spec.rb
309
314
  - spec/active_interaction/integration/string_interaction_spec.rb
310
315
  - spec/active_interaction/integration/symbol_interaction_spec.rb