paperclip 4.3.7 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of paperclip might be problematic. Click here for more details.

Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +13 -9
  3. data/Appraisals +22 -6
  4. data/CONTRIBUTING.md +16 -5
  5. data/Gemfile +2 -8
  6. data/LICENSE +1 -1
  7. data/NEWS +39 -27
  8. data/README.md +123 -101
  9. data/UPGRADING +12 -9
  10. data/features/basic_integration.feature +1 -0
  11. data/features/migration.feature +0 -24
  12. data/features/step_definitions/rails_steps.rb +0 -6
  13. data/features/step_definitions/s3_steps.rb +2 -2
  14. data/gemfiles/{4.1.gemfile → 4.2.awsv2.0.gemfile} +4 -6
  15. data/gemfiles/4.2.awsv2.1.gemfile +17 -0
  16. data/gemfiles/{4.2.gemfile → 4.2.awsv2.gemfile} +1 -0
  17. data/gemfiles/5.0.awsv2.0.gemfile +17 -0
  18. data/gemfiles/5.0.awsv2.1.gemfile +17 -0
  19. data/gemfiles/{3.2.gemfile → 5.0.awsv2.gemfile} +2 -1
  20. data/lib/paperclip.rb +2 -3
  21. data/lib/paperclip/attachment.rb +12 -10
  22. data/lib/paperclip/attachment_registry.rb +2 -1
  23. data/lib/paperclip/callbacks.rb +8 -6
  24. data/lib/paperclip/content_type_detector.rb +3 -2
  25. data/lib/paperclip/errors.rb +3 -1
  26. data/lib/paperclip/glue.rb +1 -1
  27. data/lib/paperclip/has_attached_file.rb +7 -1
  28. data/lib/paperclip/helpers.rb +14 -10
  29. data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +1 -1
  30. data/lib/paperclip/io_adapters/uri_adapter.rb +12 -29
  31. data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +4 -4
  32. data/lib/paperclip/schema.rb +2 -8
  33. data/lib/paperclip/storage/fog.rb +9 -6
  34. data/lib/paperclip/storage/s3.rb +42 -40
  35. data/lib/paperclip/validators/attachment_size_validator.rb +1 -7
  36. data/lib/paperclip/version.rb +3 -1
  37. data/lib/tasks/paperclip.rake +1 -1
  38. data/paperclip.gemspec +11 -8
  39. data/spec/paperclip/attachment_processing_spec.rb +2 -4
  40. data/spec/paperclip/attachment_registry_spec.rb +28 -0
  41. data/spec/paperclip/attachment_spec.rb +33 -10
  42. data/spec/paperclip/has_attached_file_spec.rb +24 -8
  43. data/spec/paperclip/integration_spec.rb +4 -3
  44. data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +17 -8
  45. data/spec/paperclip/io_adapters/uri_adapter_spec.rb +32 -30
  46. data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +10 -0
  47. data/spec/paperclip/paperclip_spec.rb +3 -33
  48. data/spec/paperclip/storage/fog_spec.rb +10 -0
  49. data/spec/paperclip/storage/s3_live_spec.rb +8 -4
  50. data/spec/paperclip/storage/s3_spec.rb +213 -156
  51. data/spec/paperclip/validators/attachment_size_validator_spec.rb +26 -20
  52. data/spec/paperclip/validators_spec.rb +3 -3
  53. data/spec/spec_helper.rb +3 -1
  54. data/spec/support/assertions.rb +7 -0
  55. data/spec/support/model_reconstruction.rb +9 -1
  56. data/spec/support/reporting.rb +11 -0
  57. metadata +44 -37
  58. data/cucumber/paperclip_steps.rb +0 -6
  59. data/lib/paperclip/deprecations.rb +0 -42
  60. data/lib/paperclip/locales/de.yml +0 -18
  61. data/lib/paperclip/locales/es.yml +0 -18
  62. data/lib/paperclip/locales/ja.yml +0 -18
  63. data/lib/paperclip/locales/pt-BR.yml +0 -18
  64. data/lib/paperclip/locales/zh-CN.yml +0 -18
  65. data/lib/paperclip/locales/zh-HK.yml +0 -18
  66. data/lib/paperclip/locales/zh-TW.yml +0 -18
  67. data/spec/paperclip/deprecations_spec.rb +0 -65
  68. data/spec/support/deprecations.rb +0 -9
  69. data/spec/support/rails_helpers.rb +0 -7
@@ -2,11 +2,9 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe 'Attachment Processing' do
5
- context 'using validates_attachment_content_type' do
6
- before do
7
- rebuild_class
8
- end
5
+ before { rebuild_class }
9
6
 
7
+ context 'using validates_attachment_content_type' do
10
8
  it 'processes attachments given a valid assignment' do
11
9
  file = File.new(fixture_file("5k.png"))
12
10
  Dummy.validates_attachment_content_type :avatar, content_type: "image/png"
@@ -111,6 +111,34 @@ describe 'Attachment Registry' do
111
111
 
112
112
  assert_equal expected_definitions, definitions
113
113
  end
114
+
115
+ it 'allows subclasses to override attachment defitions' do
116
+ foo_definitions = { avatar: { yo: "greeting" } }
117
+ bar_definitions = { avatar: { yo: "hello" } }
118
+
119
+ expected_definitions = {
120
+ avatar: {
121
+ yo: "hello"
122
+ }
123
+ }
124
+
125
+ foo = Class.new
126
+ bar = Class.new(foo)
127
+ Paperclip::AttachmentRegistry.register(
128
+ foo,
129
+ :avatar,
130
+ foo_definitions[:avatar]
131
+ )
132
+ Paperclip::AttachmentRegistry.register(
133
+ bar,
134
+ :avatar,
135
+ bar_definitions[:avatar]
136
+ )
137
+
138
+ definitions = Paperclip::AttachmentRegistry.definitions_for(bar)
139
+
140
+ assert_equal expected_definitions, definitions
141
+ end
114
142
  end
115
143
 
116
144
  context '.clear' do
@@ -222,9 +222,6 @@ describe Paperclip::Attachment do
222
222
  dummy.avatar_file_name = "fake.jpg"
223
223
  dummy.stubs(:new_record?).returns(false)
224
224
  expected_string = '{"avatar":"/system/dummies/avatars/000/001/234/original/fake.jpg"}'
225
- if ActiveRecord::Base.include_root_in_json # This is true by default in Rails 3, and false in 4
226
- expected_string = %({"dummy":#{expected_string}})
227
- end
228
225
  # active_model pre-3.2 checks only by calling any? on it, thus it doesn't work if it is empty
229
226
  assert_equal expected_string, dummy.to_json(only: [:dummy_key_for_old_active_model], methods: [:avatar])
230
227
  end
@@ -700,9 +697,6 @@ describe Paperclip::Attachment do
700
697
 
701
698
  context "when assigned" do
702
699
  it "calls #make on all specified processors" do
703
- Paperclip::Thumbnail.stubs(:make).with(any_parameters).returns(@file)
704
- Paperclip::Test.stubs(:make).with(any_parameters).returns(@file)
705
-
706
700
  @dummy.avatar = @file
707
701
 
708
702
  expect(Paperclip::Thumbnail).to have_received(:make)
@@ -717,7 +711,6 @@ describe Paperclip::Attachment do
717
711
  convert_options: "",
718
712
  source_file_options: ""
719
713
  })
720
- Paperclip::Thumbnail.stubs(:make).returns(@file)
721
714
 
722
715
  @dummy.avatar = @file
723
716
 
@@ -725,12 +718,36 @@ describe Paperclip::Attachment do
725
718
  end
726
719
 
727
720
  it "calls #make with attachment passed as third argument" do
728
- Paperclip::Test.expects(:make).returns(@file)
729
-
730
721
  @dummy.avatar = @file
731
722
 
732
723
  expect(Paperclip::Test).to have_received(:make).with(anything, anything, @dummy.avatar)
733
724
  end
725
+
726
+ it "calls #make and unlinks intermediary files afterward" do
727
+ @dummy.avatar.expects(:unlink_files).with([@file, @file])
728
+
729
+ @dummy.avatar = @file
730
+ end
731
+ end
732
+ end
733
+
734
+ context "An attachment with a processor that returns original file" do
735
+ before do
736
+ class Paperclip::Test < Paperclip::Processor
737
+ def make; @file; end
738
+ end
739
+ rebuild_model processors: [:test], styles: { once: "100x100" }
740
+ @file = StringIO.new("...")
741
+ @file.stubs(:close)
742
+ @dummy = Dummy.new
743
+ end
744
+
745
+ context "when assigned" do
746
+ it "#calls #make and doesn't unlink the original file" do
747
+ @dummy.avatar.expects(:unlink_files).with([])
748
+
749
+ @dummy.avatar = @file
750
+ end
734
751
  end
735
752
  end
736
753
 
@@ -1104,7 +1121,7 @@ describe Paperclip::Attachment do
1104
1121
  context "with a file assigned but not saved yet" do
1105
1122
  it "clears out any attached files" do
1106
1123
  @attachment.assign(@file)
1107
- assert !@attachment.queued_for_write.blank?
1124
+ assert @attachment.queued_for_write.present?
1108
1125
  @attachment.clear
1109
1126
  assert @attachment.queued_for_write.blank?
1110
1127
  end
@@ -1354,6 +1371,12 @@ describe Paperclip::Attachment do
1354
1371
  end
1355
1372
 
1356
1373
  it "does not calculate fingerprint" do
1374
+ Digest::MD5.stubs(:file)
1375
+ @dummy.avatar = @file
1376
+ expect(Digest::MD5).to have_received(:file).never
1377
+ end
1378
+
1379
+ it "does not assign fingerprint" do
1357
1380
  @dummy.avatar = @file
1358
1381
  assert_nil @dummy.avatar.fingerprint
1359
1382
  end
@@ -38,6 +38,15 @@ describe Paperclip::HasAttachedFile do
38
38
  assert_adding_attachment('avatar').defines_callback('after_commit')
39
39
  end
40
40
 
41
+ context 'when the class does not allow after_commit callbacks' do
42
+ it 'defines an after_destroy callback' do
43
+ assert_adding_attachment(
44
+ 'avatar',
45
+ unstub_methods: [:after_commit]
46
+ ).defines_callback('after_destroy')
47
+ end
48
+ end
49
+
41
50
  it 'defines the Paperclip-specific callbacks' do
42
51
  assert_adding_attachment('avatar').defines_callback('define_paperclip_callbacks')
43
52
  end
@@ -53,20 +62,26 @@ describe Paperclip::HasAttachedFile do
53
62
 
54
63
  private
55
64
 
56
- def assert_adding_attachment(attachment_name)
57
- AttachmentAdder.new(attachment_name)
65
+ def assert_adding_attachment(attachment_name, options={})
66
+ AttachmentAdder.new(attachment_name, options)
58
67
  end
59
68
 
60
69
  class AttachmentAdder
61
70
  include Mocha::API
62
71
  include RSpec::Matchers
63
72
 
64
- def initialize(attachment_name)
73
+ def initialize(attachment_name, options = {})
65
74
  @attachment_name = attachment_name
75
+ @stubbed_class = stub_class
76
+ if options.present?
77
+ options[:unstub_methods].each do |method|
78
+ @stubbed_class.unstub(method)
79
+ end
80
+ end
66
81
  end
67
82
 
68
83
  def defines_method(method_name)
69
- a_class = stub_class
84
+ a_class = @stubbed_class
70
85
 
71
86
  Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
72
87
 
@@ -74,7 +89,7 @@ describe Paperclip::HasAttachedFile do
74
89
  end
75
90
 
76
91
  def defines_class_method(method_name)
77
- a_class = stub_class
92
+ a_class = @stubbed_class
78
93
  a_class.class.stubs(:define_method)
79
94
 
80
95
  Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
@@ -83,7 +98,7 @@ describe Paperclip::HasAttachedFile do
83
98
  end
84
99
 
85
100
  def defines_validation
86
- a_class = stub_class
101
+ a_class = @stubbed_class
87
102
 
88
103
  Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
89
104
 
@@ -91,7 +106,7 @@ describe Paperclip::HasAttachedFile do
91
106
  end
92
107
 
93
108
  def registers_attachment
94
- a_class = stub_class
109
+ a_class = @stubbed_class
95
110
  Paperclip::AttachmentRegistry.stubs(:register)
96
111
 
97
112
  Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {size: 1})
@@ -100,7 +115,7 @@ describe Paperclip::HasAttachedFile do
100
115
  end
101
116
 
102
117
  def defines_callback(callback_name)
103
- a_class = stub_class
118
+ a_class = @stubbed_class
104
119
 
105
120
  Paperclip::HasAttachedFile.define_on(a_class, @attachment_name, {})
106
121
 
@@ -132,6 +147,7 @@ describe Paperclip::HasAttachedFile do
132
147
  after_save: nil,
133
148
  before_destroy: nil,
134
149
  after_commit: nil,
150
+ after_destroy: nil,
135
151
  define_paperclip_callbacks: nil,
136
152
  extend: nil,
137
153
  name: 'Billy',
@@ -7,9 +7,10 @@ describe 'Paperclip' do
7
7
  before do
8
8
  rebuild_model
9
9
  @file = File.new(fixture_file("5k.png"), 'rb')
10
- 300.times do |i|
11
- Dummy.create! avatar: @file
12
- end
10
+ # Deals with `Too many open files` error
11
+ Dummy.import 100.times.map { Dummy.new avatar: @file }
12
+ Dummy.import 100.times.map { Dummy.new avatar: @file }
13
+ Dummy.import 100.times.map { Dummy.new avatar: @file }
13
14
  end
14
15
 
15
16
  after { @file.close }
@@ -1,16 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Paperclip::HttpUrlProxyAdapter do
4
- before do
5
- @open_return = StringIO.new("xxx")
6
- @open_return.stubs(:content_type).returns("image/png")
7
- @open_return.stubs(:meta).returns({})
8
- Paperclip::HttpUrlProxyAdapter.any_instance.
9
- stubs(:download_content).returns(@open_return)
10
- end
11
-
12
4
  context "a new instance" do
13
5
  before do
6
+ @open_return = StringIO.new("xxx")
7
+ @open_return.stubs(:content_type).returns("image/png")
8
+ Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).returns(@open_return)
14
9
  @url = "http://thoughtbot.com/images/thoughtbot-logo.png"
15
10
  @subject = Paperclip.io_adapters.for(@url)
16
11
  end
@@ -65,6 +60,7 @@ describe Paperclip::HttpUrlProxyAdapter do
65
60
 
66
61
  context "a url with query params" do
67
62
  before do
63
+ Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).returns(StringIO.new("x"))
68
64
  @url = "https://github.com/thoughtbot/paperclip?file=test"
69
65
  @subject = Paperclip.io_adapters.for(@url)
70
66
  end
@@ -80,6 +76,7 @@ describe Paperclip::HttpUrlProxyAdapter do
80
76
 
81
77
  context "a url with restricted characters in the filename" do
82
78
  before do
79
+ Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).returns(StringIO.new("x"))
83
80
  @url = "https://github.com/thoughtbot/paper:clip.jpg"
84
81
  @subject = Paperclip.io_adapters.for(@url)
85
82
  end
@@ -101,4 +98,16 @@ describe Paperclip::HttpUrlProxyAdapter do
101
98
  end
102
99
  end
103
100
 
101
+ context "a url with special characters in the filename" do
102
+ it "returns a encoded filename" do
103
+ Paperclip::HttpUrlProxyAdapter.any_instance.stubs(:download_content).
104
+ returns(StringIO.new("x"))
105
+ url = "https://github.com/thoughtbot/paperclip-öäü字´½♥زÈ.png"
106
+ subject = Paperclip.io_adapters.for(url)
107
+ filename = "paperclip-%C3%B6%C3%A4%C3%BC%E5%AD%97%C2%B4%C2%BD%E2%99%A5"\
108
+ "%C3%98%C2%B2%C3%88.png"
109
+
110
+ assert_equal filename, subject.original_filename
111
+ end
112
+ end
104
113
  end
@@ -1,19 +1,11 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Paperclip::UriAdapter do
4
- let(:content_type) { "image/png" }
5
- let(:meta) { {} }
6
-
7
- before do
8
- @open_return = StringIO.new("xxx")
9
- @open_return.stubs(:content_type).returns(content_type)
10
- @open_return.stubs(:meta).returns(meta)
11
- Paperclip::UriAdapter.any_instance.
12
- stubs(:download_content).returns(@open_return)
13
- end
14
-
15
4
  context "a new instance" do
16
5
  before do
6
+ @open_return = StringIO.new("xxx")
7
+ @open_return.stubs(:content_type).returns("image/png")
8
+ Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(@open_return)
17
9
  @uri = URI.parse("http://thoughtbot.com/images/thoughtbot-logo.png")
18
10
  @subject = Paperclip.io_adapters.for(@uri)
19
11
  end
@@ -64,9 +56,8 @@ describe Paperclip::UriAdapter do
64
56
  end
65
57
 
66
58
  context "a directory index url" do
67
- let(:content_type) { "text/html" }
68
-
69
59
  before do
60
+ Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
70
61
  @uri = URI.parse("http://thoughtbot.com")
71
62
  @subject = Paperclip.io_adapters.for(@uri)
72
63
  end
@@ -82,6 +73,7 @@ describe Paperclip::UriAdapter do
82
73
 
83
74
  context "a url with query params" do
84
75
  before do
76
+ Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
85
77
  @uri = URI.parse("https://github.com/thoughtbot/paperclip?file=test")
86
78
  @subject = Paperclip.io_adapters.for(@uri)
87
79
  end
@@ -91,37 +83,47 @@ describe Paperclip::UriAdapter do
91
83
  end
92
84
  end
93
85
 
94
- context "a url with content disposition headers" do
95
- let(:file_name) { "test_document.pdf" }
96
- let(:meta) do
97
- {
98
- "content-disposition" => "attachment; filename=\"#{file_name}\";",
99
- }
100
- end
101
-
86
+ context "a url with restricted characters in the filename" do
102
87
  before do
103
- @uri = URI.parse("https://github.com/thoughtbot/paperclip?file=test")
88
+ Paperclip::UriAdapter.any_instance.stubs(:download_content).returns(StringIO.new("xxx"))
89
+ @uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
104
90
  @subject = Paperclip.io_adapters.for(@uri)
105
91
  end
106
92
 
107
- it "returns a file name" do
108
- assert_equal file_name, @subject.original_filename
93
+ it "does not generate filenames that include restricted characters" do
94
+ assert_equal "paper_clip.jpg", @subject.original_filename
95
+ end
96
+
97
+ it "does not generate paths that include restricted characters" do
98
+ expect(@subject.path).to_not match(/:/)
109
99
  end
110
100
  end
111
101
 
112
- context "a url with restricted characters in the filename" do
102
+ describe "#download_content" do
113
103
  before do
104
+ Paperclip::UriAdapter.any_instance.stubs(:open).returns(StringIO.new("xxx"))
114
105
  @uri = URI.parse("https://github.com/thoughtbot/paper:clip.jpg")
115
106
  @subject = Paperclip.io_adapters.for(@uri)
116
107
  end
117
108
 
118
- it "does not generate filenames that include restricted characters" do
119
- assert_equal "paper_clip.jpg", @subject.original_filename
109
+ after do
110
+ @subject.send(:download_content)
120
111
  end
121
112
 
122
- it "does not generate paths that include restricted characters" do
123
- expect(@subject.path).to_not match(/:/)
113
+ context "with default read_timeout" do
114
+ it "calls open without options" do
115
+ @subject.expects(:open).with(@uri, {}).at_least_once
116
+ end
124
117
  end
125
- end
126
118
 
119
+ context "with custom read_timeout" do
120
+ before do
121
+ Paperclip.options[:read_timeout] = 120
122
+ end
123
+
124
+ it "calls open with read_timeout option" do
125
+ @subject.expects(:open).with(@uri, read_timeout: 120).at_least_once
126
+ end
127
+ end
128
+ end
127
129
  end
@@ -17,22 +17,26 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
17
17
 
18
18
  it "rejects a class with no validation" do
19
19
  expect(matcher).to_not accept(Dummy)
20
+ expect { matcher.failure_message }.to_not raise_error
20
21
  end
21
22
 
22
23
  it 'rejects a class when the validation fails' do
23
24
  Dummy.validates_attachment_content_type :avatar, content_type: %r{audio/.*}
24
25
  expect(matcher).to_not accept(Dummy)
26
+ expect { matcher.failure_message }.to_not raise_error
25
27
  end
26
28
 
27
29
  it "accepts a class with a matching validation" do
28
30
  Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
29
31
  expect(matcher).to accept(Dummy)
32
+ expect { matcher.failure_message }.to_not raise_error
30
33
  end
31
34
 
32
35
  it "accepts a class with other validations but matching types" do
33
36
  Dummy.validates_presence_of :title
34
37
  Dummy.validates_attachment_content_type :avatar, content_type: %r{image/.*}
35
38
  expect(matcher).to accept(Dummy)
39
+ expect { matcher.failure_message }.to_not raise_error
36
40
  end
37
41
 
38
42
  it "accepts a class that matches and a matcher that only specifies 'allowing'" do
@@ -40,6 +44,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
40
44
  matcher = plain_matcher.allowing(%w(image/png image/jpeg))
41
45
 
42
46
  expect(matcher).to accept(Dummy)
47
+ expect { matcher.failure_message }.to_not raise_error
43
48
  end
44
49
 
45
50
  it "rejects a class that does not match and a matcher that only specifies 'allowing'" do
@@ -47,6 +52,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
47
52
  matcher = plain_matcher.allowing(%w(image/png image/jpeg))
48
53
 
49
54
  expect(matcher).to_not accept(Dummy)
55
+ expect { matcher.failure_message }.to_not raise_error
50
56
  end
51
57
 
52
58
  it "accepts a class that matches and a matcher that only specifies 'rejecting'" do
@@ -54,6 +60,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
54
60
  matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
55
61
 
56
62
  expect(matcher).to accept(Dummy)
63
+ expect { matcher.failure_message }.to_not raise_error
57
64
  end
58
65
 
59
66
  it "rejects a class that does not match and a matcher that only specifies 'rejecting'" do
@@ -61,6 +68,7 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
61
68
  matcher = plain_matcher.rejecting(%w(audio/mp3 application/octet-stream))
62
69
 
63
70
  expect(matcher).to_not accept(Dummy)
71
+ expect { matcher.failure_message }.to_not raise_error
64
72
  end
65
73
 
66
74
  context "using an :if to control the validation" do
@@ -75,12 +83,14 @@ describe Paperclip::Shoulda::Matchers::ValidateAttachmentContentTypeMatcher do
75
83
  dummy = Dummy.new
76
84
  dummy.go = true
77
85
  expect(matcher).to accept(dummy)
86
+ expect { matcher.failure_message }.to_not raise_error
78
87
  end
79
88
 
80
89
  it "does not run the validation if the control is false" do
81
90
  dummy = Dummy.new
82
91
  dummy.go = false
83
92
  expect(matcher).to_not accept(dummy)
93
+ expect { matcher.failure_message }.to_not raise_error
84
94
  end
85
95
  end
86
96