thoughtbot-paperclip 2.2.3 → 2.2.4
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/paperclip/attachment.rb +30 -20
- data/lib/paperclip/processor.rb +5 -4
- data/lib/paperclip/storage.rb +3 -0
- data/lib/paperclip/thumbnail.rb +1 -1
- data/lib/paperclip.rb +1 -1
- data/test/attachment_test.rb +107 -2
- data/test/helper.rb +1 -0
- data/test/processor_test.rb +2 -2
- data/test/storage_test.rb +13 -0
- metadata +2 -2
data/lib/paperclip/attachment.rb
CHANGED
@@ -28,8 +28,11 @@ module Paperclip
|
|
28
28
|
options = self.class.default_options.merge(options)
|
29
29
|
|
30
30
|
@url = options[:url]
|
31
|
+
@url = @url.call(self) if @url.is_a?(Proc)
|
31
32
|
@path = options[:path]
|
33
|
+
@path = @path.call(self) if @path.is_a?(Proc)
|
32
34
|
@styles = options[:styles]
|
35
|
+
@styles = @styles.call(self) if @styles.is_a?(Proc)
|
33
36
|
@default_url = options[:default_url]
|
34
37
|
@validations = options[:validations]
|
35
38
|
@default_style = options[:default_style]
|
@@ -188,24 +191,31 @@ module Paperclip
|
|
188
191
|
# necessary.
|
189
192
|
def self.interpolations
|
190
193
|
@interpolations ||= {
|
191
|
-
:rails_root
|
192
|
-
:rails_env
|
193
|
-
:class
|
194
|
-
|
195
|
-
|
196
|
-
:basename
|
197
|
-
|
198
|
-
|
199
|
-
:extension
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
:id
|
204
|
-
:id_partition
|
205
|
-
|
206
|
-
|
207
|
-
:attachment
|
208
|
-
:style
|
194
|
+
:rails_root => lambda{|attachment,style| RAILS_ROOT },
|
195
|
+
:rails_env => lambda{|attachment,style| RAILS_ENV },
|
196
|
+
:class => lambda do |attachment,style|
|
197
|
+
attachment.instance.class.name.underscore.pluralize
|
198
|
+
end,
|
199
|
+
:basename => lambda do |attachment,style|
|
200
|
+
attachment.original_filename.gsub(/#{File.extname(attachment.original_filename)}$/, "")
|
201
|
+
end,
|
202
|
+
:extension => lambda do |attachment,style|
|
203
|
+
((style = attachment.styles[style]) && style[:format]) ||
|
204
|
+
File.extname(attachment.original_filename).gsub(/^\.+/, "")
|
205
|
+
end,
|
206
|
+
:id => lambda{|attachment,style| attachment.instance.id },
|
207
|
+
:id_partition => lambda do |attachment, style|
|
208
|
+
("%09d" % attachment.instance.id).scan(/\d{3}/).join("/")
|
209
|
+
end,
|
210
|
+
:attachment => lambda{|attachment,style| attachment.name.to_s.downcase.pluralize },
|
211
|
+
:style => lambda{|attachment,style| style || attachment.default_style },
|
212
|
+
:relative_root => lambda do |attachment,style|
|
213
|
+
if ActionController::AbstractRequest.respond_to?(:relative_url_root)
|
214
|
+
ActionController::AbstractRequest.relative_url_root
|
215
|
+
elsif ActionController::Base.respond_to?(:relative_url_root)
|
216
|
+
ActionController::Base.relative_url_root
|
217
|
+
end
|
218
|
+
end
|
209
219
|
}
|
210
220
|
end
|
211
221
|
|
@@ -350,7 +360,7 @@ module Paperclip
|
|
350
360
|
raise RuntimeError.new("Style #{name} has no processors defined.") if args[:processors].blank?
|
351
361
|
@queued_for_write[name] = args[:processors].inject(@queued_for_write[:original]) do |file, processor|
|
352
362
|
log("Processing #{name} #{file} in the #{processor} processor.")
|
353
|
-
Paperclip.processor(processor).make(file, args)
|
363
|
+
Paperclip.processor(processor).make(file, args, self)
|
354
364
|
end
|
355
365
|
rescue PaperclipError => e
|
356
366
|
log("An error was received while processing: #{e.inspect}")
|
@@ -387,7 +397,7 @@ module Paperclip
|
|
387
397
|
|
388
398
|
def flush_errors #:nodoc:
|
389
399
|
@errors.each do |error, message|
|
390
|
-
instance.errors.add(name,
|
400
|
+
[message].flatten.each {|m| instance.errors.add(name, m) }
|
391
401
|
end
|
392
402
|
end
|
393
403
|
|
data/lib/paperclip/processor.rb
CHANGED
@@ -17,18 +17,19 @@ module Paperclip
|
|
17
17
|
# See Paperclip.run for more information about using command-line
|
18
18
|
# utilities from within Processors.
|
19
19
|
class Processor
|
20
|
-
attr_accessor :file, :options
|
20
|
+
attr_accessor :file, :options, :attachment
|
21
21
|
|
22
|
-
def initialize file, options = {}
|
22
|
+
def initialize file, options = {}, attachment = nil
|
23
23
|
@file = file
|
24
24
|
@options = options
|
25
|
+
@attachment = attachment
|
25
26
|
end
|
26
27
|
|
27
28
|
def make
|
28
29
|
end
|
29
30
|
|
30
|
-
def self.make file, options = {}
|
31
|
-
new(file, options).make
|
31
|
+
def self.make file, options = {}, attachment = nil
|
32
|
+
new(file, options, attachment).make
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
data/lib/paperclip/storage.rb
CHANGED
@@ -106,6 +106,8 @@ module Paperclip
|
|
106
106
|
# * +bucket+: This is the name of the S3 bucket that will store your files. Remember
|
107
107
|
# that the bucket must be unique across all of Amazon S3. If the bucket does not exist
|
108
108
|
# Paperclip will attempt to create it. The bucket name will not be interpolated.
|
109
|
+
# You can define the bucket as a Proc if you want to determine it's name at runtime.
|
110
|
+
# Paperclip will call that Proc with attachment as the only argument.
|
109
111
|
# * +url+: There are two options for the S3 url. You can choose to have the bucket's name
|
110
112
|
# placed domain-style (bucket.s3.amazonaws.com) or path-style (s3.amazonaws.com/bucket).
|
111
113
|
# Normally, this won't matter in the slightest and you can leave the default (which is
|
@@ -122,6 +124,7 @@ module Paperclip
|
|
122
124
|
base.instance_eval do
|
123
125
|
@s3_credentials = parse_credentials(@options[:s3_credentials])
|
124
126
|
@bucket = @options[:bucket] || @s3_credentials[:bucket]
|
127
|
+
@bucket = @bucket.call(self) if @bucket.is_a?(Proc)
|
125
128
|
@s3_options = @options[:s3_options] || {}
|
126
129
|
@s3_permissions = @options[:s3_permissions] || 'public-read'
|
127
130
|
@s3_protocol = @options[:s3_protocol] || (@s3_permissions == 'public-read' ? 'http' : 'https')
|
data/lib/paperclip/thumbnail.rb
CHANGED
@@ -10,7 +10,7 @@ module Paperclip
|
|
10
10
|
# unless specified. Thumbnail creation will raise no errors unless
|
11
11
|
# +whiny+ is true (which it is, by default. If +convert_options+ is
|
12
12
|
# set, the options will be appended to the convert command upon image conversion
|
13
|
-
def initialize file, options = {}
|
13
|
+
def initialize file, options = {}, attachment = nil
|
14
14
|
super
|
15
15
|
geometry = options[:geometry]
|
16
16
|
@file = file
|
data/lib/paperclip.rb
CHANGED
data/test/attachment_test.rb
CHANGED
@@ -106,6 +106,36 @@ class AttachmentTest < Test::Unit::TestCase
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
+
context "An attachment with a :relative_root interpolation" do
|
110
|
+
setup do
|
111
|
+
rebuild_model :url => ":relative_root/:id.png"
|
112
|
+
@dummy = Dummy.new
|
113
|
+
@dummy.stubs(:id).returns(1024)
|
114
|
+
@dummy.avatar = StringIO.new(".")
|
115
|
+
|
116
|
+
ActionController::Base.stubs(:respond_to?).with(:relative_url_root).returns(false)
|
117
|
+
ActionController::Base.stubs(:relative_url_root).returns("/base")
|
118
|
+
ActionController::AbstractRequest.stubs(:respond_to?).with(:relative_url_root).returns(false)
|
119
|
+
ActionController::AbstractRequest.stubs(:relative_url_root).returns("/request")
|
120
|
+
end
|
121
|
+
|
122
|
+
should "return the proper path when the path is nil" do
|
123
|
+
assert_equal "/1024.png", @dummy.avatar.url(:original, false)
|
124
|
+
end
|
125
|
+
|
126
|
+
should "return the proper path when using Rails < 2.1" do
|
127
|
+
ActionController::AbstractRequest.expects(:respond_to?).with(:relative_url_root).returns(true)
|
128
|
+
ActionController::AbstractRequest.expects(:relative_url_root).returns("/request")
|
129
|
+
assert_equal "/request/1024.png", @dummy.avatar.url(:original, false)
|
130
|
+
end
|
131
|
+
|
132
|
+
should "return the proper path when using Rails >= 2.1" do
|
133
|
+
ActionController::Base.expects(:respond_to?).with(:relative_url_root).returns(true)
|
134
|
+
ActionController::Base.expects(:relative_url_root).returns("/base")
|
135
|
+
assert_equal "/base/1024.png", @dummy.avatar.url(:original, false)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
109
139
|
context "An attachment with :convert_options" do
|
110
140
|
setup do
|
111
141
|
rebuild_model :styles => {
|
@@ -165,6 +195,60 @@ class AttachmentTest < Test::Unit::TestCase
|
|
165
195
|
Paperclip::Attachment.any_instance.expects(:extra_options_for).with(:large)
|
166
196
|
end
|
167
197
|
end
|
198
|
+
|
199
|
+
context "An attachment with :path that is a proc" do
|
200
|
+
setup do
|
201
|
+
rebuild_model :path => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
|
202
|
+
|
203
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
204
|
+
"fixtures",
|
205
|
+
"5k.png"), 'rb')
|
206
|
+
@dummyA = Dummy.new(:other => 'a')
|
207
|
+
@dummyA.avatar = @file
|
208
|
+
@dummyB = Dummy.new(:other => 'b')
|
209
|
+
@dummyB.avatar = @file
|
210
|
+
end
|
211
|
+
|
212
|
+
teardown { @file.close }
|
213
|
+
|
214
|
+
should "return correct path" do
|
215
|
+
assert_equal "path/a.png", @dummyA.avatar.path
|
216
|
+
assert_equal "path/b.png", @dummyB.avatar.path
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
context "An attachment with :styles that is a proc" do
|
221
|
+
setup do
|
222
|
+
rebuild_model :styles => lambda{ |attachment| {:thumb => "50x50#", :large => "400x400"} }
|
223
|
+
|
224
|
+
@attachment = Dummy.new.avatar
|
225
|
+
end
|
226
|
+
|
227
|
+
should "have the correct geometry" do
|
228
|
+
assert_equal "50x50#", @attachment.styles[:thumb][:geometry]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context "An attachment with :url that is a proc" do
|
233
|
+
setup do
|
234
|
+
rebuild_model :url => lambda{ |attachment| "path/#{attachment.instance.other}.:extension" }
|
235
|
+
|
236
|
+
@file = File.new(File.join(File.dirname(__FILE__),
|
237
|
+
"fixtures",
|
238
|
+
"5k.png"), 'rb')
|
239
|
+
@dummyA = Dummy.new(:other => 'a')
|
240
|
+
@dummyA.avatar = @file
|
241
|
+
@dummyB = Dummy.new(:other => 'b')
|
242
|
+
@dummyB.avatar = @file
|
243
|
+
end
|
244
|
+
|
245
|
+
teardown { @file.close }
|
246
|
+
|
247
|
+
should "return correct url" do
|
248
|
+
assert_equal "path/a.png", @dummyA.avatar.url(:original, false)
|
249
|
+
assert_equal "path/b.png", @dummyB.avatar.url(:original, false)
|
250
|
+
end
|
251
|
+
end
|
168
252
|
|
169
253
|
geometry_specs = [
|
170
254
|
[ lambda{|z| "50x50#" }, :png ],
|
@@ -211,6 +295,22 @@ class AttachmentTest < Test::Unit::TestCase
|
|
211
295
|
end
|
212
296
|
end
|
213
297
|
end
|
298
|
+
|
299
|
+
context "An attachment with erroring processor" do
|
300
|
+
setup do
|
301
|
+
rebuild_model :processor => [:thumbnail], :styles => { :small => '' }, :whiny_thumbnails => true
|
302
|
+
@dummy = Dummy.new
|
303
|
+
Paperclip::Thumbnail.expects(:make).raises(Paperclip::PaperclipError, "cannot be processed.")
|
304
|
+
@file = StringIO.new("...")
|
305
|
+
@file.stubs(:to_tempfile).returns(@file)
|
306
|
+
@dummy.avatar = @file
|
307
|
+
end
|
308
|
+
|
309
|
+
should "correctly forward processing error message to the instance" do
|
310
|
+
@dummy.valid?
|
311
|
+
assert_contains @dummy.errors.full_messages, "Avatar cannot be processed."
|
312
|
+
end
|
313
|
+
end
|
214
314
|
|
215
315
|
context "An attachment with multiple processors" do
|
216
316
|
setup do
|
@@ -229,8 +329,13 @@ class AttachmentTest < Test::Unit::TestCase
|
|
229
329
|
|
230
330
|
before_should "call #make on all specified processors" do
|
231
331
|
expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => nil, :convert_options => ""})
|
232
|
-
Paperclip::Thumbnail.expects(:make).with(@file, expected_params).returns(@file)
|
233
|
-
Paperclip::Test.expects(:make).with(@file, expected_params).returns(@file)
|
332
|
+
Paperclip::Thumbnail.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
|
333
|
+
Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
|
334
|
+
end
|
335
|
+
|
336
|
+
before_should "call #make with attachment passed as third argument" do
|
337
|
+
expected_params = @style_params[:once].merge({:processors => [:thumbnail, :test], :whiny => nil, :convert_options => ""})
|
338
|
+
Paperclip::Test.expects(:make).with(@file, expected_params, @dummy.avatar).returns(@file)
|
234
339
|
end
|
235
340
|
end
|
236
341
|
end
|
data/test/helper.rb
CHANGED
data/test/processor_test.rb
CHANGED
@@ -4,7 +4,7 @@ class ProcessorTest < Test::Unit::TestCase
|
|
4
4
|
should "instantiate and call #make when sent #make to the class" do
|
5
5
|
processor = mock
|
6
6
|
processor.expects(:make).with()
|
7
|
-
Paperclip::Processor.expects(:new).with(:one, :two).returns(processor)
|
8
|
-
Paperclip::Processor.make(:one, :two)
|
7
|
+
Paperclip::Processor.expects(:new).with(:one, :two, :three).returns(processor)
|
8
|
+
Paperclip::Processor.make(:one, :two, :three)
|
9
9
|
end
|
10
10
|
end
|
data/test/storage_test.rb
CHANGED
@@ -126,6 +126,19 @@ class StorageTest < Test::Unit::TestCase
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
end
|
129
|
+
|
130
|
+
context "An attachment with S3 storage and bucket defined as a Proc" do
|
131
|
+
setup do
|
132
|
+
rebuild_model :storage => :s3,
|
133
|
+
:bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
|
134
|
+
:s3_credentials => {:not => :important}
|
135
|
+
end
|
136
|
+
|
137
|
+
should "get the right bucket name" do
|
138
|
+
assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
|
139
|
+
assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
|
140
|
+
end
|
141
|
+
end
|
129
142
|
|
130
143
|
context "An attachment with S3 storage and specific s3 headers set" do
|
131
144
|
setup do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thoughtbot-paperclip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Yurek
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-02-
|
12
|
+
date: 2009-02-09 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|