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.
@@ -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 => lambda{|attachment,style| RAILS_ROOT },
192
- :rails_env => lambda{|attachment,style| RAILS_ENV },
193
- :class => lambda do |attachment,style|
194
- attachment.instance.class.name.underscore.pluralize
195
- end,
196
- :basename => lambda do |attachment,style|
197
- attachment.original_filename.gsub(/#{File.extname(attachment.original_filename)}$/, "")
198
- end,
199
- :extension => lambda do |attachment,style|
200
- ((style = attachment.styles[style]) && style[:format]) ||
201
- File.extname(attachment.original_filename).gsub(/^\.+/, "")
202
- end,
203
- :id => lambda{|attachment,style| attachment.instance.id },
204
- :id_partition => lambda do |attachment, style|
205
- ("%09d" % attachment.instance.id).scan(/\d{3}/).join("/")
206
- end,
207
- :attachment => lambda{|attachment,style| attachment.name.to_s.downcase.pluralize },
208
- :style => lambda{|attachment,style| style || attachment.default_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, message) if message
400
+ [message].flatten.each {|m| instance.errors.add(name, m) }
391
401
  end
392
402
  end
393
403
 
@@ -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
 
@@ -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')
@@ -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
@@ -43,7 +43,7 @@ end
43
43
  # documentation for Paperclip::ClassMethods for more useful information.
44
44
  module Paperclip
45
45
 
46
- VERSION = "2.2.3"
46
+ VERSION = "2.2.4"
47
47
 
48
48
  class << self
49
49
  # Provides configurability to Paperclip. There are a number of options available, such as:
@@ -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
@@ -9,6 +9,7 @@ gem 'sqlite3-ruby'
9
9
 
10
10
  require 'active_record'
11
11
  require 'active_support'
12
+ require 'action_controller'
12
13
  begin
13
14
  require 'ruby-debug'
14
15
  rescue LoadError
@@ -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.3
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-07 00:00:00 -08:00
12
+ date: 2009-02-09 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency