kt-paperclip 4.4.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 +7 -0
- data/.gitignore +19 -0
- data/.hound.yml +1066 -0
- data/.rubocop.yml +1 -0
- data/.travis.yml +23 -0
- data/Appraisals +11 -0
- data/CONTRIBUTING.md +75 -0
- data/Gemfile +21 -0
- data/LICENSE +24 -0
- data/NEWS +420 -0
- data/README.md +977 -0
- data/RELEASING.md +17 -0
- data/Rakefile +44 -0
- data/UPGRADING +14 -0
- data/cucumber/paperclip_steps.rb +6 -0
- data/features/basic_integration.feature +80 -0
- data/features/migration.feature +94 -0
- data/features/rake_tasks.feature +62 -0
- data/features/step_definitions/attachment_steps.rb +110 -0
- data/features/step_definitions/html_steps.rb +15 -0
- data/features/step_definitions/rails_steps.rb +236 -0
- data/features/step_definitions/s3_steps.rb +14 -0
- data/features/step_definitions/web_steps.rb +107 -0
- data/features/support/env.rb +11 -0
- data/features/support/fakeweb.rb +13 -0
- data/features/support/file_helpers.rb +34 -0
- data/features/support/fixtures/boot_config.txt +15 -0
- data/features/support/fixtures/gemfile.txt +5 -0
- data/features/support/fixtures/preinitializer.txt +20 -0
- data/features/support/paths.rb +28 -0
- data/features/support/rails.rb +63 -0
- data/features/support/selectors.rb +19 -0
- data/gemfiles/3.2.gemfile +19 -0
- data/gemfiles/4.1.gemfile +19 -0
- data/gemfiles/4.2.gemfile +19 -0
- data/lib/generators/paperclip/USAGE +8 -0
- data/lib/generators/paperclip/paperclip_generator.rb +30 -0
- data/lib/generators/paperclip/templates/paperclip_migration.rb.erb +15 -0
- data/lib/kt-paperclip.rb +1 -0
- data/lib/paperclip/attachment.rb +608 -0
- data/lib/paperclip/attachment_registry.rb +59 -0
- data/lib/paperclip/callbacks.rb +40 -0
- data/lib/paperclip/content_type_detector.rb +79 -0
- data/lib/paperclip/deprecations.rb +42 -0
- data/lib/paperclip/errors.rb +32 -0
- data/lib/paperclip/file_command_content_type_detector.rb +30 -0
- data/lib/paperclip/filename_cleaner.rb +16 -0
- data/lib/paperclip/geometry.rb +158 -0
- data/lib/paperclip/geometry_detector_factory.rb +48 -0
- data/lib/paperclip/geometry_parser_factory.rb +31 -0
- data/lib/paperclip/glue.rb +17 -0
- data/lib/paperclip/has_attached_file.rb +109 -0
- data/lib/paperclip/helpers.rb +56 -0
- data/lib/paperclip/interpolations/plural_cache.rb +18 -0
- data/lib/paperclip/interpolations.rb +197 -0
- data/lib/paperclip/io_adapters/abstract_adapter.rb +47 -0
- data/lib/paperclip/io_adapters/attachment_adapter.rb +36 -0
- data/lib/paperclip/io_adapters/data_uri_adapter.rb +22 -0
- data/lib/paperclip/io_adapters/empty_string_adapter.rb +18 -0
- data/lib/paperclip/io_adapters/file_adapter.rb +22 -0
- data/lib/paperclip/io_adapters/http_url_proxy_adapter.rb +16 -0
- data/lib/paperclip/io_adapters/identity_adapter.rb +12 -0
- data/lib/paperclip/io_adapters/nil_adapter.rb +34 -0
- data/lib/paperclip/io_adapters/registry.rb +32 -0
- data/lib/paperclip/io_adapters/stringio_adapter.rb +33 -0
- data/lib/paperclip/io_adapters/uploaded_file_adapter.rb +42 -0
- data/lib/paperclip/io_adapters/uri_adapter.rb +63 -0
- data/lib/paperclip/locales/de.yml +18 -0
- data/lib/paperclip/locales/en.yml +18 -0
- data/lib/paperclip/locales/es.yml +18 -0
- data/lib/paperclip/locales/ja.yml +18 -0
- data/lib/paperclip/locales/pt-BR.yml +18 -0
- data/lib/paperclip/locales/zh-CN.yml +18 -0
- data/lib/paperclip/locales/zh-HK.yml +18 -0
- data/lib/paperclip/locales/zh-TW.yml +18 -0
- data/lib/paperclip/logger.rb +21 -0
- data/lib/paperclip/matchers/have_attached_file_matcher.rb +54 -0
- data/lib/paperclip/matchers/validate_attachment_content_type_matcher.rb +100 -0
- data/lib/paperclip/matchers/validate_attachment_presence_matcher.rb +59 -0
- data/lib/paperclip/matchers/validate_attachment_size_matcher.rb +96 -0
- data/lib/paperclip/matchers.rb +64 -0
- data/lib/paperclip/media_type_spoof_detector.rb +89 -0
- data/lib/paperclip/missing_attachment_styles.rb +79 -0
- data/lib/paperclip/processor.rb +48 -0
- data/lib/paperclip/processor_helpers.rb +50 -0
- data/lib/paperclip/rails_environment.rb +25 -0
- data/lib/paperclip/railtie.rb +31 -0
- data/lib/paperclip/schema.rb +83 -0
- data/lib/paperclip/storage/filesystem.rb +90 -0
- data/lib/paperclip/storage/fog.rb +242 -0
- data/lib/paperclip/storage/s3.rb +440 -0
- data/lib/paperclip/storage.rb +3 -0
- data/lib/paperclip/style.rb +109 -0
- data/lib/paperclip/tempfile.rb +43 -0
- data/lib/paperclip/tempfile_factory.rb +23 -0
- data/lib/paperclip/thumbnail.rb +121 -0
- data/lib/paperclip/url_generator.rb +79 -0
- data/lib/paperclip/validators/attachment_content_type_validator.rb +88 -0
- data/lib/paperclip/validators/attachment_file_name_validator.rb +80 -0
- data/lib/paperclip/validators/attachment_file_type_ignorance_validator.rb +29 -0
- data/lib/paperclip/validators/attachment_presence_validator.rb +30 -0
- data/lib/paperclip/validators/attachment_size_validator.rb +115 -0
- data/lib/paperclip/validators/media_type_spoof_detection_validator.rb +27 -0
- data/lib/paperclip/validators.rb +74 -0
- data/lib/paperclip/version.rb +3 -0
- data/lib/paperclip.rb +213 -0
- data/lib/tasks/paperclip.rake +127 -0
- data/paperclip.gemspec +52 -0
- data/shoulda_macros/paperclip.rb +134 -0
- data/spec/database.yml +4 -0
- data/spec/paperclip/attachment_definitions_spec.rb +13 -0
- data/spec/paperclip/attachment_processing_spec.rb +82 -0
- data/spec/paperclip/attachment_registry_spec.rb +130 -0
- data/spec/paperclip/attachment_spec.rb +1494 -0
- data/spec/paperclip/content_type_detector_spec.rb +48 -0
- data/spec/paperclip/deprecations_spec.rb +65 -0
- data/spec/paperclip/file_command_content_type_detector_spec.rb +26 -0
- data/spec/paperclip/filename_cleaner_spec.rb +14 -0
- data/spec/paperclip/geometry_detector_spec.rb +39 -0
- data/spec/paperclip/geometry_parser_spec.rb +73 -0
- data/spec/paperclip/geometry_spec.rb +255 -0
- data/spec/paperclip/glue_spec.rb +44 -0
- data/spec/paperclip/has_attached_file_spec.rb +142 -0
- data/spec/paperclip/integration_spec.rb +667 -0
- data/spec/paperclip/interpolations_spec.rb +262 -0
- data/spec/paperclip/io_adapters/abstract_adapter_spec.rb +78 -0
- data/spec/paperclip/io_adapters/attachment_adapter_spec.rb +139 -0
- data/spec/paperclip/io_adapters/data_uri_adapter_spec.rb +83 -0
- data/spec/paperclip/io_adapters/empty_string_adapter_spec.rb +17 -0
- data/spec/paperclip/io_adapters/file_adapter_spec.rb +131 -0
- data/spec/paperclip/io_adapters/http_url_proxy_adapter_spec.rb +104 -0
- data/spec/paperclip/io_adapters/identity_adapter_spec.rb +8 -0
- data/spec/paperclip/io_adapters/nil_adapter_spec.rb +25 -0
- data/spec/paperclip/io_adapters/registry_spec.rb +35 -0
- data/spec/paperclip/io_adapters/stringio_adapter_spec.rb +64 -0
- data/spec/paperclip/io_adapters/uploaded_file_adapter_spec.rb +146 -0
- data/spec/paperclip/io_adapters/uri_adapter_spec.rb +127 -0
- data/spec/paperclip/matchers/have_attached_file_matcher_spec.rb +19 -0
- data/spec/paperclip/matchers/validate_attachment_content_type_matcher_spec.rb +99 -0
- data/spec/paperclip/matchers/validate_attachment_presence_matcher_spec.rb +69 -0
- data/spec/paperclip/matchers/validate_attachment_size_matcher_spec.rb +88 -0
- data/spec/paperclip/media_type_spoof_detector_spec.rb +79 -0
- data/spec/paperclip/meta_class_spec.rb +30 -0
- data/spec/paperclip/paperclip_missing_attachment_styles_spec.rb +84 -0
- data/spec/paperclip/paperclip_spec.rb +222 -0
- data/spec/paperclip/plural_cache_spec.rb +37 -0
- data/spec/paperclip/processor_helpers_spec.rb +57 -0
- data/spec/paperclip/processor_spec.rb +26 -0
- data/spec/paperclip/rails_environment_spec.rb +33 -0
- data/spec/paperclip/rake_spec.rb +103 -0
- data/spec/paperclip/schema_spec.rb +248 -0
- data/spec/paperclip/storage/filesystem_spec.rb +79 -0
- data/spec/paperclip/storage/fog_spec.rb +540 -0
- data/spec/paperclip/storage/s3_live_spec.rb +182 -0
- data/spec/paperclip/storage/s3_spec.rb +1526 -0
- data/spec/paperclip/style_spec.rb +255 -0
- data/spec/paperclip/tempfile_factory_spec.rb +33 -0
- data/spec/paperclip/thumbnail_spec.rb +500 -0
- data/spec/paperclip/url_generator_spec.rb +221 -0
- data/spec/paperclip/validators/attachment_content_type_validator_spec.rb +322 -0
- data/spec/paperclip/validators/attachment_file_name_validator_spec.rb +160 -0
- data/spec/paperclip/validators/attachment_presence_validator_spec.rb +85 -0
- data/spec/paperclip/validators/attachment_size_validator_spec.rb +229 -0
- data/spec/paperclip/validators/media_type_spoof_detection_validator_spec.rb +52 -0
- data/spec/paperclip/validators_spec.rb +164 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/support/assertions.rb +71 -0
- data/spec/support/deprecations.rb +9 -0
- data/spec/support/fake_model.rb +25 -0
- data/spec/support/fake_rails.rb +12 -0
- data/spec/support/fixtures/12k.png +0 -0
- data/spec/support/fixtures/50x50.png +0 -0
- data/spec/support/fixtures/5k.png +0 -0
- data/spec/support/fixtures/animated +0 -0
- data/spec/support/fixtures/animated.gif +0 -0
- data/spec/support/fixtures/animated.unknown +0 -0
- data/spec/support/fixtures/bad.png +1 -0
- data/spec/support/fixtures/empty.html +1 -0
- data/spec/support/fixtures/empty.xlsx +0 -0
- data/spec/support/fixtures/fog.yml +8 -0
- data/spec/support/fixtures/rotated.jpg +0 -0
- data/spec/support/fixtures/s3.yml +8 -0
- data/spec/support/fixtures/spaced file.jpg +0 -0
- data/spec/support/fixtures/spaced file.png +0 -0
- data/spec/support/fixtures/text.txt +1 -0
- data/spec/support/fixtures/twopage.pdf +0 -0
- data/spec/support/fixtures/uppercase.PNG +0 -0
- data/spec/support/matchers/accept.rb +5 -0
- data/spec/support/matchers/exist.rb +5 -0
- data/spec/support/matchers/have_column.rb +23 -0
- data/spec/support/mock_attachment.rb +22 -0
- data/spec/support/mock_interpolator.rb +24 -0
- data/spec/support/mock_url_generator_builder.rb +27 -0
- data/spec/support/model_reconstruction.rb +60 -0
- data/spec/support/rails_helpers.rb +7 -0
- data/spec/support/test_data.rb +13 -0
- data/spec/support/version_helper.rb +9 -0
- metadata +648 -0
@@ -0,0 +1,1494 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Paperclip::Attachment do
|
5
|
+
|
6
|
+
it "is not present when file not set" do
|
7
|
+
rebuild_class
|
8
|
+
dummy = Dummy.new
|
9
|
+
expect(dummy.avatar).to be_blank
|
10
|
+
expect(dummy.avatar).to_not be_present
|
11
|
+
end
|
12
|
+
|
13
|
+
it "is present when the file is set" do
|
14
|
+
rebuild_class
|
15
|
+
dummy = Dummy.new
|
16
|
+
dummy.avatar = File.new(fixture_file("50x50.png"), "rb")
|
17
|
+
expect(dummy.avatar).to_not be_blank
|
18
|
+
expect(dummy.avatar).to be_present
|
19
|
+
end
|
20
|
+
|
21
|
+
it "processes :original style first" do
|
22
|
+
file = File.new(fixture_file("50x50.png"), 'rb')
|
23
|
+
rebuild_class styles: { small: '100x>', original: '42x42#' }
|
24
|
+
dummy = Dummy.new
|
25
|
+
dummy.avatar = file
|
26
|
+
dummy.save
|
27
|
+
|
28
|
+
# :small avatar should be 42px wide (processed original), not 50px (preprocessed original)
|
29
|
+
expect(`identify -format "%w" "#{dummy.avatar.path(:small)}"`.strip).to eq "42"
|
30
|
+
|
31
|
+
file.close
|
32
|
+
end
|
33
|
+
|
34
|
+
it "does not delete styles that don't get reprocessed" do
|
35
|
+
file = File.new(fixture_file("50x50.png"), 'rb')
|
36
|
+
rebuild_class styles: {
|
37
|
+
small: "100x>",
|
38
|
+
large: "500x>",
|
39
|
+
original: "42x42#"
|
40
|
+
}
|
41
|
+
|
42
|
+
dummy = Dummy.new
|
43
|
+
dummy.avatar = file
|
44
|
+
dummy.save
|
45
|
+
|
46
|
+
expect(dummy.avatar.path(:small)).to exist
|
47
|
+
expect(dummy.avatar.path(:large)).to exist
|
48
|
+
expect(dummy.avatar.path(:original)).to exist
|
49
|
+
|
50
|
+
dummy.avatar.reprocess!(:small)
|
51
|
+
|
52
|
+
expect(dummy.avatar.path(:small)).to exist
|
53
|
+
expect(dummy.avatar.path(:large)).to exist
|
54
|
+
expect(dummy.avatar.path(:original)).to exist
|
55
|
+
end
|
56
|
+
|
57
|
+
context "having a not empty hash as a default option" do
|
58
|
+
before do
|
59
|
+
@old_default_options = Paperclip::Attachment.default_options.dup
|
60
|
+
@new_default_options = { convert_options: { all: "-background white" } }
|
61
|
+
Paperclip::Attachment.default_options.merge!(@new_default_options)
|
62
|
+
end
|
63
|
+
|
64
|
+
after do
|
65
|
+
Paperclip::Attachment.default_options.merge!(@old_default_options)
|
66
|
+
end
|
67
|
+
|
68
|
+
it "deep merges when it is overridden" do
|
69
|
+
new_options = { convert_options: { thumb: "-thumbnailize" } }
|
70
|
+
attachment = Paperclip::Attachment.new(:name, :instance, new_options)
|
71
|
+
|
72
|
+
expect(Paperclip::Attachment.default_options.deep_merge(new_options)).to eq attachment.instance_variable_get("@options")
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "handles a boolean second argument to #url" do
|
77
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
78
|
+
attachment = Paperclip::Attachment.new(
|
79
|
+
:name,
|
80
|
+
FakeModel.new,
|
81
|
+
url_generator: mock_url_generator_builder
|
82
|
+
)
|
83
|
+
|
84
|
+
attachment.url(:style_name, true)
|
85
|
+
expect(mock_url_generator_builder.has_generated_url_with_options?(timestamp: true, escape: true)).to eq true
|
86
|
+
|
87
|
+
attachment.url(:style_name, false)
|
88
|
+
expect(mock_url_generator_builder.has_generated_url_with_options?(timestamp: false, escape: true)).to eq true
|
89
|
+
end
|
90
|
+
|
91
|
+
it "passes the style and options through to the URL generator on #url" do
|
92
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
93
|
+
attachment = Paperclip::Attachment.new(
|
94
|
+
:name,
|
95
|
+
FakeModel.new,
|
96
|
+
url_generator: mock_url_generator_builder
|
97
|
+
)
|
98
|
+
|
99
|
+
attachment.url(:style_name, options: :values)
|
100
|
+
expect(mock_url_generator_builder.has_generated_url_with_options?(options: :values)).to eq true
|
101
|
+
end
|
102
|
+
|
103
|
+
it "passes default options through when #url is given one argument" do
|
104
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
105
|
+
attachment = Paperclip::Attachment.new(:name,
|
106
|
+
FakeModel.new,
|
107
|
+
url_generator: mock_url_generator_builder,
|
108
|
+
use_timestamp: true)
|
109
|
+
|
110
|
+
attachment.url(:style_name)
|
111
|
+
assert mock_url_generator_builder.has_generated_url_with_options?(escape: true, timestamp: true)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "passes default style and options through when #url is given no arguments" do
|
115
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
116
|
+
attachment = Paperclip::Attachment.new(:name,
|
117
|
+
FakeModel.new,
|
118
|
+
default_style: 'default style',
|
119
|
+
url_generator: mock_url_generator_builder,
|
120
|
+
use_timestamp: true)
|
121
|
+
|
122
|
+
attachment.url
|
123
|
+
assert mock_url_generator_builder.has_generated_url_with_options?(escape: true, timestamp: true)
|
124
|
+
assert mock_url_generator_builder.has_generated_url_with_style_name?('default style')
|
125
|
+
end
|
126
|
+
|
127
|
+
it "passes the option timestamp: true if :use_timestamp is true and :timestamp is not passed" do
|
128
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
129
|
+
attachment = Paperclip::Attachment.new(:name,
|
130
|
+
FakeModel.new,
|
131
|
+
url_generator: mock_url_generator_builder,
|
132
|
+
use_timestamp: true)
|
133
|
+
|
134
|
+
attachment.url(:style_name)
|
135
|
+
assert mock_url_generator_builder.has_generated_url_with_options?(escape: true, timestamp: true)
|
136
|
+
end
|
137
|
+
|
138
|
+
it "passes the option timestamp: false if :use_timestamp is false and :timestamp is not passed" do
|
139
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
140
|
+
attachment = Paperclip::Attachment.new(:name,
|
141
|
+
FakeModel.new,
|
142
|
+
url_generator: mock_url_generator_builder,
|
143
|
+
use_timestamp: false)
|
144
|
+
|
145
|
+
attachment.url(:style_name)
|
146
|
+
assert mock_url_generator_builder.has_generated_url_with_options?(escape: true, timestamp: false)
|
147
|
+
end
|
148
|
+
|
149
|
+
it "does not change the :timestamp if :timestamp is passed" do
|
150
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
151
|
+
attachment = Paperclip::Attachment.new(:name,
|
152
|
+
FakeModel.new,
|
153
|
+
url_generator: mock_url_generator_builder,
|
154
|
+
use_timestamp: false)
|
155
|
+
|
156
|
+
attachment.url(:style_name, timestamp: true)
|
157
|
+
assert mock_url_generator_builder.has_generated_url_with_options?(escape: true, timestamp: true)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "renders JSON as default style" do
|
161
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
162
|
+
attachment = Paperclip::Attachment.new(:name,
|
163
|
+
FakeModel.new,
|
164
|
+
default_style: 'default style',
|
165
|
+
url_generator: mock_url_generator_builder)
|
166
|
+
|
167
|
+
attachment.as_json
|
168
|
+
assert mock_url_generator_builder.has_generated_url_with_style_name?('default style')
|
169
|
+
end
|
170
|
+
|
171
|
+
it "passes the option escape: true if :escape_url is true and :escape is not passed" do
|
172
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
173
|
+
attachment = Paperclip::Attachment.new(:name,
|
174
|
+
FakeModel.new,
|
175
|
+
url_generator: mock_url_generator_builder,
|
176
|
+
escape_url: true)
|
177
|
+
|
178
|
+
attachment.url(:style_name)
|
179
|
+
assert mock_url_generator_builder.has_generated_url_with_options?(escape: true)
|
180
|
+
end
|
181
|
+
|
182
|
+
it "passes the option escape: false if :escape_url is false and :escape is not passed" do
|
183
|
+
mock_url_generator_builder = MockUrlGeneratorBuilder.new
|
184
|
+
attachment = Paperclip::Attachment.new(:name,
|
185
|
+
FakeModel.new,
|
186
|
+
url_generator: mock_url_generator_builder,
|
187
|
+
escape_url: false)
|
188
|
+
|
189
|
+
attachment.url(:style_name)
|
190
|
+
assert mock_url_generator_builder.has_generated_url_with_options?(escape: false)
|
191
|
+
end
|
192
|
+
|
193
|
+
it "returns the path based on the url by default" do
|
194
|
+
@attachment = attachment url: "/:class/:id/:basename"
|
195
|
+
@model = @attachment.instance
|
196
|
+
@model.id = 1234
|
197
|
+
@model.avatar_file_name = "fake.jpg"
|
198
|
+
assert_equal "#{Rails.root}/public/fake_models/1234/fake", @attachment.path
|
199
|
+
end
|
200
|
+
|
201
|
+
it "defaults to a path that scales" do
|
202
|
+
avatar_attachment = attachment
|
203
|
+
model = avatar_attachment.instance
|
204
|
+
model.id = 1234
|
205
|
+
model.avatar_file_name = "fake.jpg"
|
206
|
+
expected_path = "#{Rails.root}/public/system/fake_models/avatars/000/001/234/original/fake.jpg"
|
207
|
+
assert_equal expected_path, avatar_attachment.path
|
208
|
+
end
|
209
|
+
|
210
|
+
it "renders JSON as the URL to the attachment" do
|
211
|
+
avatar_attachment = attachment
|
212
|
+
model = avatar_attachment.instance
|
213
|
+
model.id = 1234
|
214
|
+
model.avatar_file_name = "fake.jpg"
|
215
|
+
assert_equal attachment.url, attachment.as_json
|
216
|
+
end
|
217
|
+
|
218
|
+
it "renders JSON from the model when requested by :methods" do
|
219
|
+
rebuild_model
|
220
|
+
dummy = Dummy.new
|
221
|
+
dummy.id = 1234
|
222
|
+
dummy.avatar_file_name = "fake.jpg"
|
223
|
+
dummy.stubs(:new_record?).returns(false)
|
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
|
+
# active_model pre-3.2 checks only by calling any? on it, thus it doesn't work if it is empty
|
229
|
+
assert_equal expected_string, dummy.to_json(only: [:dummy_key_for_old_active_model], methods: [:avatar])
|
230
|
+
end
|
231
|
+
|
232
|
+
context "Attachment default_options" do
|
233
|
+
before do
|
234
|
+
rebuild_model
|
235
|
+
@old_default_options = Paperclip::Attachment.default_options.dup
|
236
|
+
@new_default_options = @old_default_options.merge({
|
237
|
+
path: "argle/bargle",
|
238
|
+
url: "fooferon",
|
239
|
+
default_url: "not here.png"
|
240
|
+
})
|
241
|
+
end
|
242
|
+
|
243
|
+
after do
|
244
|
+
Paperclip::Attachment.default_options.merge! @old_default_options
|
245
|
+
end
|
246
|
+
|
247
|
+
it "is overrideable" do
|
248
|
+
Paperclip::Attachment.default_options.merge!(@new_default_options)
|
249
|
+
@new_default_options.keys.each do |key|
|
250
|
+
assert_equal @new_default_options[key],
|
251
|
+
Paperclip::Attachment.default_options[key]
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
context "without an Attachment" do
|
256
|
+
before do
|
257
|
+
rebuild_model default_url: "default.url"
|
258
|
+
@dummy = Dummy.new
|
259
|
+
end
|
260
|
+
|
261
|
+
it "returns false when asked exists?" do
|
262
|
+
assert !@dummy.avatar.exists?
|
263
|
+
end
|
264
|
+
|
265
|
+
it "#url returns the default_url" do
|
266
|
+
expect(@dummy.avatar.url).to eq "default.url"
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
context "on an Attachment" do
|
271
|
+
before do
|
272
|
+
@dummy = Dummy.new
|
273
|
+
@attachment = @dummy.avatar
|
274
|
+
end
|
275
|
+
|
276
|
+
Paperclip::Attachment.default_options.keys.each do |key|
|
277
|
+
it "is the default_options for #{key}" do
|
278
|
+
assert_equal @old_default_options[key],
|
279
|
+
@attachment.instance_variable_get("@options")[key],
|
280
|
+
key.to_s
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
context "when redefined" do
|
285
|
+
before do
|
286
|
+
Paperclip::Attachment.default_options.merge!(@new_default_options)
|
287
|
+
@dummy = Dummy.new
|
288
|
+
@attachment = @dummy.avatar
|
289
|
+
end
|
290
|
+
|
291
|
+
Paperclip::Attachment.default_options.keys.each do |key|
|
292
|
+
it "is the new default_options for #{key}" do
|
293
|
+
assert_equal @new_default_options[key],
|
294
|
+
@attachment.instance_variable_get("@options")[key],
|
295
|
+
key.to_s
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
context "An attachment with similarly named interpolations" do
|
303
|
+
before do
|
304
|
+
rebuild_model path: ":id.omg/:id-bbq/:idwhat/:id_partition.wtf"
|
305
|
+
@dummy = Dummy.new
|
306
|
+
@dummy.stubs(:id).returns(1024)
|
307
|
+
@file = File.new(fixture_file("5k.png"), 'rb')
|
308
|
+
@dummy.avatar = @file
|
309
|
+
end
|
310
|
+
|
311
|
+
after { @file.close }
|
312
|
+
|
313
|
+
it "makes sure that they are interpolated correctly" do
|
314
|
+
assert_equal "1024.omg/1024-bbq/1024what/000/001/024.wtf", @dummy.avatar.path
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
context "An attachment with :timestamp interpolations" do
|
319
|
+
before do
|
320
|
+
@file = StringIO.new("...")
|
321
|
+
@zone = 'UTC'
|
322
|
+
Time.stubs(:zone).returns(@zone)
|
323
|
+
@zone_default = 'Eastern Time (US & Canada)'
|
324
|
+
Time.stubs(:zone_default).returns(@zone_default)
|
325
|
+
end
|
326
|
+
|
327
|
+
context "using default time zone" do
|
328
|
+
before do
|
329
|
+
rebuild_model path: ":timestamp", use_default_time_zone: true
|
330
|
+
@dummy = Dummy.new
|
331
|
+
@dummy.avatar = @file
|
332
|
+
end
|
333
|
+
|
334
|
+
it "returns a time in the default zone" do
|
335
|
+
assert_equal @dummy.avatar_updated_at.in_time_zone(@zone_default).to_s, @dummy.avatar.path
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
context "using per-thread time zone" do
|
340
|
+
before do
|
341
|
+
rebuild_model path: ":timestamp", use_default_time_zone: false
|
342
|
+
@dummy = Dummy.new
|
343
|
+
@dummy.avatar = @file
|
344
|
+
end
|
345
|
+
|
346
|
+
it "returns a time in the per-thread zone" do
|
347
|
+
assert_equal @dummy.avatar_updated_at.in_time_zone(@zone).to_s, @dummy.avatar.path
|
348
|
+
end
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
context "An attachment with :hash interpolations" do
|
353
|
+
before do
|
354
|
+
@file = File.open(fixture_file("5k.png"))
|
355
|
+
end
|
356
|
+
|
357
|
+
after do
|
358
|
+
@file.close
|
359
|
+
end
|
360
|
+
|
361
|
+
it "raises if no secret is provided" do
|
362
|
+
rebuild_model path: ":hash"
|
363
|
+
@attachment = Dummy.new.avatar
|
364
|
+
@attachment.assign @file
|
365
|
+
|
366
|
+
assert_raises ArgumentError do
|
367
|
+
@attachment.path
|
368
|
+
end
|
369
|
+
end
|
370
|
+
|
371
|
+
context "when secret is set" do
|
372
|
+
before do
|
373
|
+
rebuild_model path: ":hash",
|
374
|
+
hash_secret: "w00t",
|
375
|
+
hash_data: ":class/:attachment/:style/:filename"
|
376
|
+
@attachment = Dummy.new.avatar
|
377
|
+
@attachment.assign @file
|
378
|
+
end
|
379
|
+
|
380
|
+
it "results in the correct interpolation" do
|
381
|
+
assert_equal "dummies/avatars/original/5k.png",
|
382
|
+
@attachment.send(:interpolate, @attachment.options[:hash_data])
|
383
|
+
assert_equal "dummies/avatars/thumb/5k.png",
|
384
|
+
@attachment.send(:interpolate, @attachment.options[:hash_data], :thumb)
|
385
|
+
end
|
386
|
+
|
387
|
+
it "results in a correct hash" do
|
388
|
+
assert_equal "0a59e9142bba11576de1d353d8747b1acad5ad34", @attachment.path
|
389
|
+
assert_equal "b39a062c1e62e85a6c785ed00cf3bebf5f850e2b", @attachment.path(:thumb)
|
390
|
+
end
|
391
|
+
end
|
392
|
+
end
|
393
|
+
|
394
|
+
context "An attachment with a :rails_env interpolation" do
|
395
|
+
before do
|
396
|
+
@rails_env = "blah"
|
397
|
+
@id = 1024
|
398
|
+
rebuild_model path: ":rails_env/:id.png"
|
399
|
+
@dummy = Dummy.new
|
400
|
+
@dummy.stubs(:id).returns(@id)
|
401
|
+
@file = StringIO.new(".")
|
402
|
+
@dummy.avatar = @file
|
403
|
+
Rails.stubs(:env).returns(@rails_env)
|
404
|
+
end
|
405
|
+
|
406
|
+
it "returns the proper path" do
|
407
|
+
assert_equal "#{@rails_env}/#{@id}.png", @dummy.avatar.path
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
context "An attachment with a default style and an extension interpolation" do
|
412
|
+
before do
|
413
|
+
rebuild_model path: ":basename.:extension",
|
414
|
+
styles: { default: ["100x100", :jpg] },
|
415
|
+
default_style: :default
|
416
|
+
@attachment = Dummy.new.avatar
|
417
|
+
@file = File.open(fixture_file("5k.png"))
|
418
|
+
@file.stubs(:original_filename).returns("file.png")
|
419
|
+
end
|
420
|
+
it "returns the right extension for the path" do
|
421
|
+
@attachment.assign(@file)
|
422
|
+
assert_equal "file.jpg", @attachment.path
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
context "An attachment with :convert_options" do
|
427
|
+
before do
|
428
|
+
rebuild_model styles: {
|
429
|
+
thumb: "100x100",
|
430
|
+
large: "400x400"
|
431
|
+
},
|
432
|
+
convert_options: {
|
433
|
+
all: "-do_stuff",
|
434
|
+
thumb: "-thumbnailize"
|
435
|
+
}
|
436
|
+
@dummy = Dummy.new
|
437
|
+
@dummy.avatar
|
438
|
+
end
|
439
|
+
|
440
|
+
it "reports the correct options when sent #extra_options_for(:thumb)" do
|
441
|
+
assert_equal "-thumbnailize -do_stuff", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
|
442
|
+
end
|
443
|
+
|
444
|
+
it "reports the correct options when sent #extra_options_for(:large)" do
|
445
|
+
assert_equal "-do_stuff", @dummy.avatar.send(:extra_options_for, :large)
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
context "An attachment with :source_file_options" do
|
450
|
+
before do
|
451
|
+
rebuild_model styles: {
|
452
|
+
thumb: "100x100",
|
453
|
+
large: "400x400"
|
454
|
+
},
|
455
|
+
source_file_options: {
|
456
|
+
all: "-density 400",
|
457
|
+
thumb: "-depth 8"
|
458
|
+
}
|
459
|
+
@dummy = Dummy.new
|
460
|
+
@dummy.avatar
|
461
|
+
end
|
462
|
+
|
463
|
+
it "reports the correct options when sent #extra_source_file_options_for(:thumb)" do
|
464
|
+
assert_equal "-depth 8 -density 400", @dummy.avatar.send(:extra_source_file_options_for, :thumb), @dummy.avatar.source_file_options.inspect
|
465
|
+
end
|
466
|
+
|
467
|
+
it "reports the correct options when sent #extra_source_file_options_for(:large)" do
|
468
|
+
assert_equal "-density 400", @dummy.avatar.send(:extra_source_file_options_for, :large)
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
context "An attachment with :only_process" do
|
473
|
+
before do
|
474
|
+
rebuild_model styles: {
|
475
|
+
thumb: "100x100",
|
476
|
+
large: "400x400"
|
477
|
+
},
|
478
|
+
only_process: [:thumb]
|
479
|
+
@file = StringIO.new("...")
|
480
|
+
@attachment = Dummy.new.avatar
|
481
|
+
end
|
482
|
+
|
483
|
+
it "only processes the provided style" do
|
484
|
+
@attachment.expects(:post_process).with(:thumb)
|
485
|
+
@attachment.expects(:post_process).with(:large).never
|
486
|
+
@attachment.assign(@file)
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
context "An attachment with :only_process that is a proc" do
|
491
|
+
before do
|
492
|
+
rebuild_model styles: {
|
493
|
+
thumb: "100x100",
|
494
|
+
large: "400x400"
|
495
|
+
},
|
496
|
+
only_process: lambda { |attachment| [:thumb] }
|
497
|
+
|
498
|
+
@file = StringIO.new("...")
|
499
|
+
@attachment = Dummy.new.avatar
|
500
|
+
end
|
501
|
+
|
502
|
+
it "only processes the provided style" do
|
503
|
+
@attachment.expects(:post_process).with(:thumb)
|
504
|
+
@attachment.expects(:post_process).with(:large).never
|
505
|
+
@attachment.assign(@file)
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
context "An attachment with :convert_options that is a proc" do
|
510
|
+
before do
|
511
|
+
rebuild_model styles: {
|
512
|
+
thumb: "100x100",
|
513
|
+
large: "400x400"
|
514
|
+
},
|
515
|
+
convert_options: {
|
516
|
+
all: lambda{|i| i.all },
|
517
|
+
thumb: lambda{|i| i.thumb }
|
518
|
+
}
|
519
|
+
Dummy.class_eval do
|
520
|
+
def all; "-all"; end
|
521
|
+
def thumb; "-thumb"; end
|
522
|
+
end
|
523
|
+
@dummy = Dummy.new
|
524
|
+
@dummy.avatar
|
525
|
+
end
|
526
|
+
|
527
|
+
it "reports the correct options when sent #extra_options_for(:thumb)" do
|
528
|
+
assert_equal "-thumb -all", @dummy.avatar.send(:extra_options_for, :thumb), @dummy.avatar.convert_options.inspect
|
529
|
+
end
|
530
|
+
|
531
|
+
it "reports the correct options when sent #extra_options_for(:large)" do
|
532
|
+
assert_equal "-all", @dummy.avatar.send(:extra_options_for, :large)
|
533
|
+
end
|
534
|
+
end
|
535
|
+
|
536
|
+
context "An attachment with :path that is a proc" do
|
537
|
+
before do
|
538
|
+
rebuild_model path: lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
|
539
|
+
|
540
|
+
@file = File.new(fixture_file("5k.png"), 'rb')
|
541
|
+
@dummyA = Dummy.new(other: 'a')
|
542
|
+
@dummyA.avatar = @file
|
543
|
+
@dummyB = Dummy.new(other: 'b')
|
544
|
+
@dummyB.avatar = @file
|
545
|
+
end
|
546
|
+
|
547
|
+
after { @file.close }
|
548
|
+
|
549
|
+
it "returns correct path" do
|
550
|
+
assert_equal "path/a.png", @dummyA.avatar.path
|
551
|
+
assert_equal "path/b.png", @dummyB.avatar.path
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
context "An attachment with :styles that is a proc" do
|
556
|
+
before do
|
557
|
+
rebuild_model styles: lambda{ |attachment| {thumb: "50x50#", large: "400x400"} }
|
558
|
+
|
559
|
+
@attachment = Dummy.new.avatar
|
560
|
+
end
|
561
|
+
|
562
|
+
it "has the correct geometry" do
|
563
|
+
assert_equal "50x50#", @attachment.styles[:thumb][:geometry]
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
context "An attachment with conditional :styles that is a proc" do
|
568
|
+
before do
|
569
|
+
rebuild_model styles: lambda{ |attachment| attachment.instance.other == 'a' ? {thumb: "50x50#"} : {large: "400x400"} }
|
570
|
+
|
571
|
+
@dummy = Dummy.new(other: 'a')
|
572
|
+
end
|
573
|
+
|
574
|
+
it "has the correct styles for the assigned instance values" do
|
575
|
+
assert_equal "50x50#", @dummy.avatar.styles[:thumb][:geometry]
|
576
|
+
assert_nil @dummy.avatar.styles[:large]
|
577
|
+
|
578
|
+
@dummy.other = 'b'
|
579
|
+
|
580
|
+
assert_equal "400x400", @dummy.avatar.styles[:large][:geometry]
|
581
|
+
assert_nil @dummy.avatar.styles[:thumb]
|
582
|
+
end
|
583
|
+
end
|
584
|
+
|
585
|
+
geometry_specs = [
|
586
|
+
[ lambda{|z| "50x50#" }, :png ],
|
587
|
+
lambda{|z| "50x50#" },
|
588
|
+
{ geometry: lambda{|z| "50x50#" } }
|
589
|
+
]
|
590
|
+
geometry_specs.each do |geometry_spec|
|
591
|
+
context "An attachment geometry like #{geometry_spec}" do
|
592
|
+
before do
|
593
|
+
rebuild_model styles: { normal: geometry_spec }
|
594
|
+
@attachment = Dummy.new.avatar
|
595
|
+
end
|
596
|
+
|
597
|
+
context "when assigned" do
|
598
|
+
before do
|
599
|
+
@file = StringIO.new(".")
|
600
|
+
@attachment.assign(@file)
|
601
|
+
end
|
602
|
+
|
603
|
+
it "has the correct geometry" do
|
604
|
+
assert_equal "50x50#", @attachment.styles[:normal][:geometry]
|
605
|
+
end
|
606
|
+
end
|
607
|
+
end
|
608
|
+
end
|
609
|
+
|
610
|
+
context "An attachment with both 'normal' and hash-style styles" do
|
611
|
+
before do
|
612
|
+
rebuild_model styles: {
|
613
|
+
normal: ["50x50#", :png],
|
614
|
+
hash: { geometry: "50x50#", format: :png }
|
615
|
+
}
|
616
|
+
@dummy = Dummy.new
|
617
|
+
@attachment = @dummy.avatar
|
618
|
+
end
|
619
|
+
|
620
|
+
[:processors, :whiny, :convert_options, :geometry, :format].each do |field|
|
621
|
+
it "has the same #{field} field" do
|
622
|
+
assert_equal @attachment.styles[:normal][field], @attachment.styles[:hash][field]
|
623
|
+
end
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
context "An attachment with :processors that is a proc" do
|
628
|
+
before do
|
629
|
+
class Paperclip::Test < Paperclip::Processor; end
|
630
|
+
@file = StringIO.new("...")
|
631
|
+
Paperclip::Test.stubs(:make).returns(@file)
|
632
|
+
|
633
|
+
rebuild_model styles: { normal: '' }, processors: lambda { |a| [ :test ] }
|
634
|
+
@attachment = Dummy.new.avatar
|
635
|
+
end
|
636
|
+
|
637
|
+
context "when assigned" do
|
638
|
+
before do
|
639
|
+
@attachment.assign(StringIO.new("."))
|
640
|
+
end
|
641
|
+
|
642
|
+
it "has the correct processors" do
|
643
|
+
assert_equal [ :test ], @attachment.styles[:normal][:processors]
|
644
|
+
end
|
645
|
+
end
|
646
|
+
end
|
647
|
+
|
648
|
+
context "An attachment with erroring processor" do
|
649
|
+
before do
|
650
|
+
rebuild_model processor: [:thumbnail], styles: { small: '' }, whiny_thumbnails: true
|
651
|
+
@dummy = Dummy.new
|
652
|
+
@file = StringIO.new("...")
|
653
|
+
@file.stubs(:to_tempfile).returns(@file)
|
654
|
+
end
|
655
|
+
|
656
|
+
context "when error is meaningful for the end user" do
|
657
|
+
before do
|
658
|
+
Paperclip::Thumbnail.expects(:make).raises(
|
659
|
+
Paperclip::Errors::NotIdentifiedByImageMagickError,
|
660
|
+
"cannot be processed."
|
661
|
+
)
|
662
|
+
end
|
663
|
+
|
664
|
+
it "correctly forwards processing error message to the instance" do
|
665
|
+
@dummy.avatar = @file
|
666
|
+
@dummy.valid?
|
667
|
+
assert_contains(
|
668
|
+
@dummy.errors.full_messages,
|
669
|
+
"Avatar cannot be processed."
|
670
|
+
)
|
671
|
+
end
|
672
|
+
end
|
673
|
+
|
674
|
+
context "when error is intended for the developer" do
|
675
|
+
before do
|
676
|
+
Paperclip::Thumbnail.expects(:make).raises(
|
677
|
+
Paperclip::Errors::CommandNotFoundError
|
678
|
+
)
|
679
|
+
end
|
680
|
+
|
681
|
+
it "propagates the error" do
|
682
|
+
assert_raises(Paperclip::Errors::CommandNotFoundError) do
|
683
|
+
@dummy.avatar = @file
|
684
|
+
end
|
685
|
+
end
|
686
|
+
end
|
687
|
+
end
|
688
|
+
|
689
|
+
context "An attachment with multiple processors" do
|
690
|
+
before do
|
691
|
+
class Paperclip::Test < Paperclip::Processor; end
|
692
|
+
@style_params = { once: {one: 1, two: 2} }
|
693
|
+
rebuild_model processors: [:thumbnail, :test], styles: @style_params
|
694
|
+
@dummy = Dummy.new
|
695
|
+
@file = StringIO.new("...")
|
696
|
+
@file.stubs(:close)
|
697
|
+
Paperclip::Test.stubs(:make).returns(@file)
|
698
|
+
Paperclip::Thumbnail.stubs(:make).returns(@file)
|
699
|
+
end
|
700
|
+
|
701
|
+
context "when assigned" do
|
702
|
+
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
|
+
@dummy.avatar = @file
|
707
|
+
|
708
|
+
expect(Paperclip::Thumbnail).to have_received(:make)
|
709
|
+
expect(Paperclip::Test).to have_received(:make)
|
710
|
+
end
|
711
|
+
|
712
|
+
it "calls #make with the right parameters passed as second argument" do
|
713
|
+
expected_params = @style_params[:once].merge({
|
714
|
+
style: :once,
|
715
|
+
processors: [:thumbnail, :test],
|
716
|
+
whiny: true,
|
717
|
+
convert_options: "",
|
718
|
+
source_file_options: ""
|
719
|
+
})
|
720
|
+
Paperclip::Thumbnail.stubs(:make).returns(@file)
|
721
|
+
|
722
|
+
@dummy.avatar = @file
|
723
|
+
|
724
|
+
expect(Paperclip::Thumbnail).to have_received(:make).with(anything, expected_params, anything)
|
725
|
+
end
|
726
|
+
|
727
|
+
it "calls #make with attachment passed as third argument" do
|
728
|
+
Paperclip::Test.expects(:make).returns(@file)
|
729
|
+
|
730
|
+
@dummy.avatar = @file
|
731
|
+
|
732
|
+
expect(Paperclip::Test).to have_received(:make).with(anything, anything, @dummy.avatar)
|
733
|
+
end
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
it "includes the filesystem module when loading the filesystem storage" do
|
738
|
+
rebuild_model storage: :filesystem
|
739
|
+
@dummy = Dummy.new
|
740
|
+
assert @dummy.avatar.is_a?(Paperclip::Storage::Filesystem)
|
741
|
+
end
|
742
|
+
|
743
|
+
it "includes the filesystem module even if capitalization is wrong" do
|
744
|
+
rebuild_model storage: :FileSystem
|
745
|
+
@dummy = Dummy.new
|
746
|
+
assert @dummy.avatar.is_a?(Paperclip::Storage::Filesystem)
|
747
|
+
|
748
|
+
rebuild_model storage: :Filesystem
|
749
|
+
@dummy = Dummy.new
|
750
|
+
assert @dummy.avatar.is_a?(Paperclip::Storage::Filesystem)
|
751
|
+
end
|
752
|
+
|
753
|
+
it "converts underscored storage name to camelcase" do
|
754
|
+
rebuild_model storage: :not_here
|
755
|
+
@dummy = Dummy.new
|
756
|
+
exception = assert_raises(Paperclip::Errors::StorageMethodNotFound, /NotHere/) do
|
757
|
+
@dummy.avatar
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
it "raises an error if you try to include a storage module that doesn't exist" do
|
762
|
+
rebuild_model storage: :not_here
|
763
|
+
@dummy = Dummy.new
|
764
|
+
assert_raises(Paperclip::Errors::StorageMethodNotFound) do
|
765
|
+
@dummy.avatar
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
context "An attachment with styles but no processors defined" do
|
770
|
+
before do
|
771
|
+
rebuild_model processors: [], styles: {something: '1'}
|
772
|
+
@dummy = Dummy.new
|
773
|
+
@file = StringIO.new("...")
|
774
|
+
end
|
775
|
+
it "raises when assigned to" do
|
776
|
+
assert_raises(RuntimeError){ @dummy.avatar = @file }
|
777
|
+
end
|
778
|
+
end
|
779
|
+
|
780
|
+
context "An attachment without styles and with no processors defined" do
|
781
|
+
before do
|
782
|
+
rebuild_model processors: [], styles: {}
|
783
|
+
@dummy = Dummy.new
|
784
|
+
@file = StringIO.new("...")
|
785
|
+
end
|
786
|
+
it "does not raise when assigned to" do
|
787
|
+
@dummy.avatar = @file
|
788
|
+
end
|
789
|
+
end
|
790
|
+
|
791
|
+
context "Assigning an attachment with post_process hooks" do
|
792
|
+
before do
|
793
|
+
rebuild_class styles: { something: "100x100#" }
|
794
|
+
Dummy.class_eval do
|
795
|
+
before_avatar_post_process :do_before_avatar
|
796
|
+
after_avatar_post_process :do_after_avatar
|
797
|
+
before_post_process :do_before_all
|
798
|
+
after_post_process :do_after_all
|
799
|
+
def do_before_avatar; end
|
800
|
+
def do_after_avatar; end
|
801
|
+
def do_before_all; end
|
802
|
+
def do_after_all; end
|
803
|
+
end
|
804
|
+
@file = StringIO.new(".")
|
805
|
+
@file.stubs(:to_tempfile).returns(@file)
|
806
|
+
@dummy = Dummy.new
|
807
|
+
Paperclip::Thumbnail.stubs(:make).returns(@file)
|
808
|
+
@attachment = @dummy.avatar
|
809
|
+
end
|
810
|
+
|
811
|
+
it "calls the defined callbacks when assigned" do
|
812
|
+
@dummy.expects(:do_before_avatar).with()
|
813
|
+
@dummy.expects(:do_after_avatar).with()
|
814
|
+
@dummy.expects(:do_before_all).with()
|
815
|
+
@dummy.expects(:do_after_all).with()
|
816
|
+
Paperclip::Thumbnail.expects(:make).returns(@file)
|
817
|
+
@dummy.avatar = @file
|
818
|
+
end
|
819
|
+
|
820
|
+
it "does not cancel the processing if a before_post_process returns nil" do
|
821
|
+
@dummy.expects(:do_before_avatar).with().returns(nil)
|
822
|
+
@dummy.expects(:do_after_avatar).with()
|
823
|
+
@dummy.expects(:do_before_all).with().returns(nil)
|
824
|
+
@dummy.expects(:do_after_all).with()
|
825
|
+
Paperclip::Thumbnail.expects(:make).returns(@file)
|
826
|
+
@dummy.avatar = @file
|
827
|
+
end
|
828
|
+
|
829
|
+
it "cancels the processing if a before_post_process returns false" do
|
830
|
+
@dummy.expects(:do_before_avatar).never
|
831
|
+
@dummy.expects(:do_after_avatar).never
|
832
|
+
@dummy.expects(:do_before_all).with().returns(false)
|
833
|
+
@dummy.expects(:do_after_all)
|
834
|
+
Paperclip::Thumbnail.expects(:make).never
|
835
|
+
@dummy.avatar = @file
|
836
|
+
end
|
837
|
+
|
838
|
+
it "cancels the processing if a before_avatar_post_process returns false" do
|
839
|
+
@dummy.expects(:do_before_avatar).with().returns(false)
|
840
|
+
@dummy.expects(:do_after_avatar)
|
841
|
+
@dummy.expects(:do_before_all).with().returns(true)
|
842
|
+
@dummy.expects(:do_after_all)
|
843
|
+
Paperclip::Thumbnail.expects(:make).never
|
844
|
+
@dummy.avatar = @file
|
845
|
+
end
|
846
|
+
end
|
847
|
+
|
848
|
+
context "Assigning an attachment" do
|
849
|
+
before do
|
850
|
+
rebuild_model styles: { something: "100x100#" }
|
851
|
+
@file = File.new(fixture_file("5k.png"), "rb")
|
852
|
+
@dummy = Dummy.new
|
853
|
+
@dummy.avatar = @file
|
854
|
+
end
|
855
|
+
|
856
|
+
it "strips whitespace from original_filename field" do
|
857
|
+
assert_equal "5k.png", @dummy.avatar.original_filename
|
858
|
+
end
|
859
|
+
|
860
|
+
it "strips whitespace from content_type field" do
|
861
|
+
assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
|
862
|
+
end
|
863
|
+
end
|
864
|
+
|
865
|
+
context "Assigning an attachment" do
|
866
|
+
before do
|
867
|
+
rebuild_model styles: { something: "100x100#" }
|
868
|
+
@file = File.new(fixture_file("5k.png"), "rb")
|
869
|
+
@dummy = Dummy.new
|
870
|
+
@dummy.avatar = @file
|
871
|
+
end
|
872
|
+
|
873
|
+
it "makes sure the content_type is a string" do
|
874
|
+
assert_equal "image/png", @dummy.avatar.instance.avatar_content_type
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
context "Attachment with strange letters" do
|
879
|
+
before do
|
880
|
+
rebuild_model
|
881
|
+
@file = File.new(fixture_file("5k.png"), "rb")
|
882
|
+
@file.stubs(:original_filename).returns("sheep_say_bæ.png")
|
883
|
+
@dummy = Dummy.new
|
884
|
+
@dummy.avatar = @file
|
885
|
+
end
|
886
|
+
|
887
|
+
it "does not remove strange letters" do
|
888
|
+
assert_equal "sheep_say_bæ.png", @dummy.avatar.original_filename
|
889
|
+
end
|
890
|
+
end
|
891
|
+
|
892
|
+
context "Attachment with reserved filename" do
|
893
|
+
before do
|
894
|
+
rebuild_model
|
895
|
+
@file = Tempfile.new(["filename","png"])
|
896
|
+
end
|
897
|
+
|
898
|
+
after do
|
899
|
+
@file.unlink
|
900
|
+
end
|
901
|
+
|
902
|
+
context "with default configuration" do
|
903
|
+
"&$+,/:;=?@<>[]{}|\^~%# ".split(//).each do |character|
|
904
|
+
context "with character #{character}" do
|
905
|
+
|
906
|
+
context "at beginning of filename" do
|
907
|
+
before do
|
908
|
+
@file.stubs(:original_filename).returns("#{character}filename.png")
|
909
|
+
@dummy = Dummy.new
|
910
|
+
@dummy.avatar = @file
|
911
|
+
end
|
912
|
+
|
913
|
+
it "converts special character into underscore" do
|
914
|
+
assert_equal "_filename.png", @dummy.avatar.original_filename
|
915
|
+
end
|
916
|
+
end
|
917
|
+
|
918
|
+
context "at end of filename" do
|
919
|
+
before do
|
920
|
+
@file.stubs(:original_filename).returns("filename.png#{character}")
|
921
|
+
@dummy = Dummy.new
|
922
|
+
@dummy.avatar = @file
|
923
|
+
end
|
924
|
+
|
925
|
+
it "converts special character into underscore" do
|
926
|
+
assert_equal "filename.png_", @dummy.avatar.original_filename
|
927
|
+
end
|
928
|
+
end
|
929
|
+
|
930
|
+
context "in the middle of filename" do
|
931
|
+
before do
|
932
|
+
@file.stubs(:original_filename).returns("file#{character}name.png")
|
933
|
+
@dummy = Dummy.new
|
934
|
+
@dummy.avatar = @file
|
935
|
+
end
|
936
|
+
|
937
|
+
it "converts special character into underscore" do
|
938
|
+
assert_equal "file_name.png", @dummy.avatar.original_filename
|
939
|
+
end
|
940
|
+
end
|
941
|
+
|
942
|
+
end
|
943
|
+
end
|
944
|
+
end
|
945
|
+
|
946
|
+
context "with specified regexp replacement" do
|
947
|
+
before do
|
948
|
+
@old_defaults = Paperclip::Attachment.default_options.dup
|
949
|
+
end
|
950
|
+
|
951
|
+
after do
|
952
|
+
Paperclip::Attachment.default_options.merge! @old_defaults
|
953
|
+
end
|
954
|
+
|
955
|
+
context 'as another regexp' do
|
956
|
+
before do
|
957
|
+
Paperclip::Attachment.default_options.merge! restricted_characters: /o/
|
958
|
+
|
959
|
+
@file.stubs(:original_filename).returns("goood.png")
|
960
|
+
@dummy = Dummy.new
|
961
|
+
@dummy.avatar = @file
|
962
|
+
end
|
963
|
+
|
964
|
+
it "matches and converts that character" do
|
965
|
+
assert_equal "g___d.png", @dummy.avatar.original_filename
|
966
|
+
end
|
967
|
+
end
|
968
|
+
|
969
|
+
context 'as nil' do
|
970
|
+
before do
|
971
|
+
Paperclip::Attachment.default_options.merge! restricted_characters: nil
|
972
|
+
|
973
|
+
@file.stubs(:original_filename).returns("goood.png")
|
974
|
+
@dummy = Dummy.new
|
975
|
+
@dummy.avatar = @file
|
976
|
+
end
|
977
|
+
|
978
|
+
it "ignores and returns the original file name" do
|
979
|
+
assert_equal "goood.png", @dummy.avatar.original_filename
|
980
|
+
end
|
981
|
+
end
|
982
|
+
end
|
983
|
+
|
984
|
+
context 'with specified cleaner' do
|
985
|
+
before do
|
986
|
+
@old_defaults = Paperclip::Attachment.default_options.dup
|
987
|
+
end
|
988
|
+
|
989
|
+
after do
|
990
|
+
Paperclip::Attachment.default_options.merge! @old_defaults
|
991
|
+
end
|
992
|
+
|
993
|
+
it 'calls the given proc and take the result as cleaned filename' do
|
994
|
+
Paperclip::Attachment.default_options[:filename_cleaner] = lambda do |str|
|
995
|
+
"from_proc_#{str}"
|
996
|
+
end
|
997
|
+
|
998
|
+
@file.stubs(:original_filename).returns("goood.png")
|
999
|
+
@dummy = Dummy.new
|
1000
|
+
@dummy.avatar = @file
|
1001
|
+
assert_equal "from_proc_goood.png", @dummy.avatar.original_filename
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
it 'calls the given object and take the result as the cleaned filename' do
|
1005
|
+
class MyCleaner
|
1006
|
+
def call(filename)
|
1007
|
+
"foo"
|
1008
|
+
end
|
1009
|
+
end
|
1010
|
+
Paperclip::Attachment.default_options[:filename_cleaner] = MyCleaner.new
|
1011
|
+
|
1012
|
+
@file.stubs(:original_filename).returns("goood.png")
|
1013
|
+
@dummy = Dummy.new
|
1014
|
+
@dummy.avatar = @file
|
1015
|
+
assert_equal "foo", @dummy.avatar.original_filename
|
1016
|
+
end
|
1017
|
+
end
|
1018
|
+
end
|
1019
|
+
|
1020
|
+
context "Attachment with uppercase extension and a default style" do
|
1021
|
+
before do
|
1022
|
+
@old_defaults = Paperclip::Attachment.default_options.dup
|
1023
|
+
Paperclip::Attachment.default_options.merge!({
|
1024
|
+
path: ":rails_root/:attachment/:class/:style/:id/:basename.:extension"
|
1025
|
+
})
|
1026
|
+
FileUtils.rm_rf("tmp")
|
1027
|
+
rebuild_model styles: { large: ["400x400", :jpg],
|
1028
|
+
medium: ["100x100", :jpg],
|
1029
|
+
small: ["32x32#", :jpg]},
|
1030
|
+
default_style: :small
|
1031
|
+
@instance = Dummy.new
|
1032
|
+
@instance.stubs(:id).returns 123
|
1033
|
+
@file = File.new(fixture_file("uppercase.PNG"), 'rb')
|
1034
|
+
|
1035
|
+
@attachment = @instance.avatar
|
1036
|
+
|
1037
|
+
now = Time.now
|
1038
|
+
Time.stubs(:now).returns(now)
|
1039
|
+
@attachment.assign(@file)
|
1040
|
+
@attachment.save
|
1041
|
+
end
|
1042
|
+
|
1043
|
+
after do
|
1044
|
+
@file.close
|
1045
|
+
Paperclip::Attachment.default_options.merge!(@old_defaults)
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
it "has matching to_s and url methods" do
|
1049
|
+
assert_equal @attachment.to_s, @attachment.url
|
1050
|
+
assert_equal @attachment.to_s(:small), @attachment.url(:small)
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
it "has matching expiring_url and url methods when using the filesystem storage" do
|
1054
|
+
assert_equal @attachment.expiring_url, @attachment.url
|
1055
|
+
end
|
1056
|
+
end
|
1057
|
+
|
1058
|
+
context "An attachment" do
|
1059
|
+
before do
|
1060
|
+
@old_defaults = Paperclip::Attachment.default_options.dup
|
1061
|
+
Paperclip::Attachment.default_options.merge!({
|
1062
|
+
path: ":rails_root/:attachment/:class/:style/:id/:basename.:extension"
|
1063
|
+
})
|
1064
|
+
FileUtils.rm_rf("tmp")
|
1065
|
+
rebuild_model
|
1066
|
+
@instance = Dummy.new
|
1067
|
+
@instance.stubs(:id).returns 123
|
1068
|
+
# @attachment = Paperclip::Attachment.new(:avatar, @instance)
|
1069
|
+
@attachment = @instance.avatar
|
1070
|
+
@file = File.new(fixture_file("5k.png"), 'rb')
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
after do
|
1074
|
+
@file.close
|
1075
|
+
Paperclip::Attachment.default_options.merge!(@old_defaults)
|
1076
|
+
end
|
1077
|
+
|
1078
|
+
it "raises if there are not the correct columns when you try to assign" do
|
1079
|
+
@other_attachment = Paperclip::Attachment.new(:not_here, @instance)
|
1080
|
+
assert_raises(Paperclip::Error) do
|
1081
|
+
@other_attachment.assign(@file)
|
1082
|
+
end
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
it 'clears out the previous assignment when assigned nil' do
|
1086
|
+
@attachment.assign(@file)
|
1087
|
+
@attachment.queued_for_write[:original]
|
1088
|
+
@attachment.assign(nil)
|
1089
|
+
assert_nil @attachment.queued_for_write[:original]
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
it 'does not do anything when it is assigned an empty string' do
|
1093
|
+
@attachment.assign(@file)
|
1094
|
+
original_file = @attachment.queued_for_write[:original]
|
1095
|
+
@attachment.assign("")
|
1096
|
+
assert_equal original_file, @attachment.queued_for_write[:original]
|
1097
|
+
end
|
1098
|
+
|
1099
|
+
it "returns nil as path when no file assigned" do
|
1100
|
+
assert_equal nil, @attachment.path
|
1101
|
+
assert_equal nil, @attachment.path(:blah)
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
context "with a file assigned but not saved yet" do
|
1105
|
+
it "clears out any attached files" do
|
1106
|
+
@attachment.assign(@file)
|
1107
|
+
assert !@attachment.queued_for_write.blank?
|
1108
|
+
@attachment.clear
|
1109
|
+
assert @attachment.queued_for_write.blank?
|
1110
|
+
end
|
1111
|
+
end
|
1112
|
+
|
1113
|
+
context "with a file assigned in the database" do
|
1114
|
+
before do
|
1115
|
+
@attachment.stubs(:instance_read).with(:file_name).returns("5k.png")
|
1116
|
+
@attachment.stubs(:instance_read).with(:content_type).returns("image/png")
|
1117
|
+
@attachment.stubs(:instance_read).with(:file_size).returns(12345)
|
1118
|
+
dtnow = DateTime.now
|
1119
|
+
@now = Time.now
|
1120
|
+
Time.stubs(:now).returns(@now)
|
1121
|
+
@attachment.stubs(:instance_read).with(:updated_at).returns(dtnow)
|
1122
|
+
end
|
1123
|
+
|
1124
|
+
it "returns the proper path when filename has a single .'s" do
|
1125
|
+
assert_equal File.expand_path("tmp/avatars/dummies/original/#{@instance.id}/5k.png"), File.expand_path(@attachment.path)
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
it "returns the proper path when filename has multiple .'s" do
|
1129
|
+
@attachment.stubs(:instance_read).with(:file_name).returns("5k.old.png")
|
1130
|
+
assert_equal File.expand_path("tmp/avatars/dummies/original/#{@instance.id}/5k.old.png"), File.expand_path(@attachment.path)
|
1131
|
+
end
|
1132
|
+
|
1133
|
+
context "when expecting three styles" do
|
1134
|
+
before do
|
1135
|
+
rebuild_class styles: {
|
1136
|
+
large: ["400x400", :png],
|
1137
|
+
medium: ["100x100", :gif],
|
1138
|
+
small: ["32x32#", :jpg]
|
1139
|
+
}
|
1140
|
+
@instance = Dummy.new
|
1141
|
+
@instance.stubs(:id).returns 123
|
1142
|
+
@file = File.new(fixture_file("5k.png"), 'rb')
|
1143
|
+
@attachment = @instance.avatar
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
context "and assigned a file" do
|
1147
|
+
before do
|
1148
|
+
now = Time.now
|
1149
|
+
Time.stubs(:now).returns(now)
|
1150
|
+
@attachment.assign(@file)
|
1151
|
+
end
|
1152
|
+
|
1153
|
+
it "is dirty" do
|
1154
|
+
assert @attachment.dirty?
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
context "and saved" do
|
1158
|
+
before do
|
1159
|
+
@attachment.save
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
it "commits the files to disk" do
|
1163
|
+
[:large, :medium, :small].each do |style|
|
1164
|
+
expect(@attachment.path(style)).to exist
|
1165
|
+
end
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
it "saves the files as the right formats and sizes" do
|
1169
|
+
[[:large, 400, 61, "PNG"],
|
1170
|
+
[:medium, 100, 15, "GIF"],
|
1171
|
+
[:small, 32, 32, "JPEG"]].each do |style|
|
1172
|
+
cmd = %Q[identify -format "%w %h %b %m" "#{@attachment.path(style.first)}"]
|
1173
|
+
out = `#{cmd}`
|
1174
|
+
width, height, _size, format = out.split(" ")
|
1175
|
+
assert_equal style[1].to_s, width.to_s
|
1176
|
+
assert_equal style[2].to_s, height.to_s
|
1177
|
+
assert_equal style[3].to_s, format.to_s
|
1178
|
+
end
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
context "and trying to delete" do
|
1182
|
+
before do
|
1183
|
+
@existing_names = @attachment.styles.keys.collect do |style|
|
1184
|
+
@attachment.path(style)
|
1185
|
+
end
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
it "deletes the files after assigning nil" do
|
1189
|
+
@attachment.expects(:instance_write).with(:file_name, nil)
|
1190
|
+
@attachment.expects(:instance_write).with(:content_type, nil)
|
1191
|
+
@attachment.expects(:instance_write).with(:file_size, nil)
|
1192
|
+
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
1193
|
+
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1194
|
+
@attachment.assign nil
|
1195
|
+
@attachment.save
|
1196
|
+
@existing_names.each{|f| assert_file_not_exists(f) }
|
1197
|
+
end
|
1198
|
+
|
1199
|
+
it "deletes the files when you call #clear and #save" do
|
1200
|
+
@attachment.expects(:instance_write).with(:file_name, nil)
|
1201
|
+
@attachment.expects(:instance_write).with(:content_type, nil)
|
1202
|
+
@attachment.expects(:instance_write).with(:file_size, nil)
|
1203
|
+
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
1204
|
+
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1205
|
+
@attachment.clear
|
1206
|
+
@attachment.save
|
1207
|
+
@existing_names.each{|f| assert_file_not_exists(f) }
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
it "deletes the files when you call #delete" do
|
1211
|
+
@attachment.expects(:instance_write).with(:file_name, nil)
|
1212
|
+
@attachment.expects(:instance_write).with(:content_type, nil)
|
1213
|
+
@attachment.expects(:instance_write).with(:file_size, nil)
|
1214
|
+
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
1215
|
+
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1216
|
+
@attachment.destroy
|
1217
|
+
@existing_names.each{|f| assert_file_not_exists(f) }
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
context "when keeping old files" do
|
1221
|
+
before do
|
1222
|
+
@attachment.options[:keep_old_files] = true
|
1223
|
+
end
|
1224
|
+
|
1225
|
+
it "keeps the files after assigning nil" do
|
1226
|
+
@attachment.expects(:instance_write).with(:file_name, nil)
|
1227
|
+
@attachment.expects(:instance_write).with(:content_type, nil)
|
1228
|
+
@attachment.expects(:instance_write).with(:file_size, nil)
|
1229
|
+
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
1230
|
+
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1231
|
+
@attachment.assign nil
|
1232
|
+
@attachment.save
|
1233
|
+
@existing_names.each{|f| assert_file_exists(f) }
|
1234
|
+
end
|
1235
|
+
|
1236
|
+
it "keeps the files when you call #clear and #save" do
|
1237
|
+
@attachment.expects(:instance_write).with(:file_name, nil)
|
1238
|
+
@attachment.expects(:instance_write).with(:content_type, nil)
|
1239
|
+
@attachment.expects(:instance_write).with(:file_size, nil)
|
1240
|
+
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
1241
|
+
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1242
|
+
@attachment.clear
|
1243
|
+
@attachment.save
|
1244
|
+
@existing_names.each{|f| assert_file_exists(f) }
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
it "keeps the files when you call #delete" do
|
1248
|
+
@attachment.expects(:instance_write).with(:file_name, nil)
|
1249
|
+
@attachment.expects(:instance_write).with(:content_type, nil)
|
1250
|
+
@attachment.expects(:instance_write).with(:file_size, nil)
|
1251
|
+
@attachment.expects(:instance_write).with(:fingerprint, nil)
|
1252
|
+
@attachment.expects(:instance_write).with(:updated_at, nil)
|
1253
|
+
@attachment.destroy
|
1254
|
+
@existing_names.each{|f| assert_file_exists(f) }
|
1255
|
+
end
|
1256
|
+
end
|
1257
|
+
end
|
1258
|
+
end
|
1259
|
+
end
|
1260
|
+
end
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
context "when trying a nonexistant storage type" do
|
1264
|
+
before do
|
1265
|
+
rebuild_model storage: :not_here
|
1266
|
+
end
|
1267
|
+
|
1268
|
+
it "is not able to find the module" do
|
1269
|
+
assert_raises(Paperclip::Errors::StorageMethodNotFound){ Dummy.new.avatar }
|
1270
|
+
end
|
1271
|
+
end
|
1272
|
+
end
|
1273
|
+
|
1274
|
+
context "An attachment with only a avatar_file_name column" do
|
1275
|
+
before do
|
1276
|
+
ActiveRecord::Base.connection.create_table :dummies, force: true do |table|
|
1277
|
+
table.column :avatar_file_name, :string
|
1278
|
+
end
|
1279
|
+
rebuild_class
|
1280
|
+
@dummy = Dummy.new
|
1281
|
+
@file = File.new(fixture_file("5k.png"), 'rb')
|
1282
|
+
end
|
1283
|
+
|
1284
|
+
after { @file.close }
|
1285
|
+
|
1286
|
+
it "does not error when assigned an attachment" do
|
1287
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
1288
|
+
end
|
1289
|
+
|
1290
|
+
it "does not return the time when sent #avatar_updated_at" do
|
1291
|
+
@dummy.avatar = @file
|
1292
|
+
assert_nil @dummy.avatar.updated_at
|
1293
|
+
end
|
1294
|
+
|
1295
|
+
it "returns the right value when sent #avatar_file_size" do
|
1296
|
+
@dummy.avatar = @file
|
1297
|
+
assert_equal File.size(@file), @dummy.avatar.size
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
context "and avatar_created_at column" do
|
1301
|
+
before do
|
1302
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_created_at, :timestamp
|
1303
|
+
rebuild_class
|
1304
|
+
@dummy = Dummy.new
|
1305
|
+
end
|
1306
|
+
|
1307
|
+
it "does not error when assigned an attachment" do
|
1308
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
it "returns the creation time when sent #avatar_created_at" do
|
1312
|
+
now = Time.now
|
1313
|
+
Time.stubs(:now).returns(now)
|
1314
|
+
@dummy.avatar = @file
|
1315
|
+
assert_equal now.to_i, @dummy.avatar.created_at
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
it "returns the creation time when sent #avatar_created_at and the entry has been updated" do
|
1319
|
+
creation = 2.hours.ago
|
1320
|
+
now = Time.now
|
1321
|
+
Time.stubs(:now).returns(creation)
|
1322
|
+
@dummy.avatar = @file
|
1323
|
+
Time.stubs(:now).returns(now)
|
1324
|
+
@dummy.avatar = @file
|
1325
|
+
assert_equal creation.to_i, @dummy.avatar.created_at
|
1326
|
+
assert_not_equal now.to_i, @dummy.avatar.created_at
|
1327
|
+
end
|
1328
|
+
|
1329
|
+
it "sets changed? to true on attachment assignment" do
|
1330
|
+
@dummy.avatar = @file
|
1331
|
+
@dummy.save!
|
1332
|
+
@dummy.avatar = @file
|
1333
|
+
assert @dummy.changed?
|
1334
|
+
end
|
1335
|
+
end
|
1336
|
+
|
1337
|
+
context "and avatar_updated_at column" do
|
1338
|
+
before do
|
1339
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_updated_at, :timestamp
|
1340
|
+
rebuild_class
|
1341
|
+
@dummy = Dummy.new
|
1342
|
+
end
|
1343
|
+
|
1344
|
+
it "does not error when assigned an attachment" do
|
1345
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
1346
|
+
end
|
1347
|
+
|
1348
|
+
it "returns the right value when sent #avatar_updated_at" do
|
1349
|
+
now = Time.now
|
1350
|
+
Time.stubs(:now).returns(now)
|
1351
|
+
@dummy.avatar = @file
|
1352
|
+
assert_equal now.to_i, @dummy.avatar.updated_at
|
1353
|
+
end
|
1354
|
+
end
|
1355
|
+
|
1356
|
+
it "does not calculate fingerprint" do
|
1357
|
+
@dummy.avatar = @file
|
1358
|
+
assert_nil @dummy.avatar.fingerprint
|
1359
|
+
end
|
1360
|
+
|
1361
|
+
context "and avatar_content_type column" do
|
1362
|
+
before do
|
1363
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_content_type, :string
|
1364
|
+
rebuild_class
|
1365
|
+
@dummy = Dummy.new
|
1366
|
+
end
|
1367
|
+
|
1368
|
+
it "does not error when assigned an attachment" do
|
1369
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
1370
|
+
end
|
1371
|
+
|
1372
|
+
it "returns the right value when sent #avatar_content_type" do
|
1373
|
+
@dummy.avatar = @file
|
1374
|
+
assert_equal "image/png", @dummy.avatar.content_type
|
1375
|
+
end
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
context "and avatar_file_size column" do
|
1379
|
+
before do
|
1380
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_file_size, :integer
|
1381
|
+
rebuild_class
|
1382
|
+
@dummy = Dummy.new
|
1383
|
+
end
|
1384
|
+
|
1385
|
+
it "does not error when assigned an attachment" do
|
1386
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
1387
|
+
end
|
1388
|
+
|
1389
|
+
it "returns the right value when sent #avatar_file_size" do
|
1390
|
+
@dummy.avatar = @file
|
1391
|
+
assert_equal File.size(@file), @dummy.avatar.size
|
1392
|
+
end
|
1393
|
+
|
1394
|
+
it "returns the right value when saved, reloaded, and sent #avatar_file_size" do
|
1395
|
+
@dummy.avatar = @file
|
1396
|
+
@dummy.save
|
1397
|
+
@dummy = Dummy.find(@dummy.id)
|
1398
|
+
assert_equal File.size(@file), @dummy.avatar.size
|
1399
|
+
end
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
context "and avatar_fingerprint column" do
|
1403
|
+
before do
|
1404
|
+
ActiveRecord::Base.connection.add_column :dummies, :avatar_fingerprint, :string
|
1405
|
+
rebuild_class
|
1406
|
+
@dummy = Dummy.new
|
1407
|
+
end
|
1408
|
+
|
1409
|
+
it "does not error when assigned an attachment" do
|
1410
|
+
assert_nothing_raised { @dummy.avatar = @file }
|
1411
|
+
end
|
1412
|
+
|
1413
|
+
it "returns the right value when sent #avatar_fingerprint" do
|
1414
|
+
@dummy.avatar = @file
|
1415
|
+
assert_equal 'aec488126c3b33c08a10c3fa303acf27', @dummy.avatar_fingerprint
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
it "returns the right value when saved, reloaded, and sent #avatar_fingerprint" do
|
1419
|
+
@dummy.avatar = @file
|
1420
|
+
@dummy.save
|
1421
|
+
@dummy = Dummy.find(@dummy.id)
|
1422
|
+
assert_equal 'aec488126c3b33c08a10c3fa303acf27', @dummy.avatar_fingerprint
|
1423
|
+
end
|
1424
|
+
end
|
1425
|
+
end
|
1426
|
+
|
1427
|
+
context "an attachment with delete_file option set to false" do
|
1428
|
+
before do
|
1429
|
+
rebuild_model preserve_files: true
|
1430
|
+
@dummy = Dummy.new
|
1431
|
+
@file = File.new(fixture_file("5k.png"), 'rb')
|
1432
|
+
@dummy.avatar = @file
|
1433
|
+
@dummy.save!
|
1434
|
+
@attachment = @dummy.avatar
|
1435
|
+
@path = @attachment.path
|
1436
|
+
end
|
1437
|
+
|
1438
|
+
after { @file.close }
|
1439
|
+
|
1440
|
+
it "does not delete the files from storage when attachment is destroyed" do
|
1441
|
+
@attachment.destroy
|
1442
|
+
assert_file_exists(@path)
|
1443
|
+
end
|
1444
|
+
|
1445
|
+
it "clears out attachment data when attachment is destroyed" do
|
1446
|
+
@attachment.destroy
|
1447
|
+
assert !@attachment.exists?
|
1448
|
+
assert_nil @dummy.avatar_file_name
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
it "does not delete the file when model is destroyed" do
|
1452
|
+
@dummy.destroy
|
1453
|
+
assert_file_exists(@path)
|
1454
|
+
end
|
1455
|
+
end
|
1456
|
+
|
1457
|
+
context "An attached file" do
|
1458
|
+
before do
|
1459
|
+
rebuild_model
|
1460
|
+
@dummy = Dummy.new
|
1461
|
+
@file = File.new(fixture_file("5k.png"), 'rb')
|
1462
|
+
@dummy.avatar = @file
|
1463
|
+
@dummy.save!
|
1464
|
+
@attachment = @dummy.avatar
|
1465
|
+
@path = @attachment.path
|
1466
|
+
end
|
1467
|
+
|
1468
|
+
after { @file.close }
|
1469
|
+
|
1470
|
+
it "is not deleted when the model fails to destroy" do
|
1471
|
+
@dummy.stubs(:destroy).raises(Exception)
|
1472
|
+
|
1473
|
+
assert_raises Exception do
|
1474
|
+
@dummy.destroy
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
assert_file_exists(@path)
|
1478
|
+
end
|
1479
|
+
|
1480
|
+
it "is deleted when the model is destroyed" do
|
1481
|
+
@dummy.destroy
|
1482
|
+
assert_file_not_exists(@path)
|
1483
|
+
end
|
1484
|
+
|
1485
|
+
it "is not deleted when transaction rollbacks after model is destroyed" do
|
1486
|
+
ActiveRecord::Base.transaction do
|
1487
|
+
@dummy.destroy
|
1488
|
+
raise ActiveRecord::Rollback
|
1489
|
+
end
|
1490
|
+
|
1491
|
+
assert_file_exists(@path)
|
1492
|
+
end
|
1493
|
+
end
|
1494
|
+
end
|