ripta-dm-paperclip 2.2.9.2 → 2.5.0.1
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.
- data/README.rdoc +12 -1
- data/Rakefile +10 -2
- data/lib/dm-paperclip.rb +79 -44
- data/lib/dm-paperclip/attachment.rb +11 -9
- data/lib/dm-paperclip/interpolations.rb +7 -7
- data/lib/dm-paperclip/iostream.rb +4 -3
- data/lib/dm-paperclip/storage.rb +71 -57
- data/lib/dm-paperclip/validations.rb +40 -5
- data/test/attachment_test.rb +19 -16
- data/test/geometry_test.rb +1 -1
- data/test/helper.rb +17 -5
- data/test/iostream_test.rb +42 -24
- data/test/paperclip_test.rb +1 -1
- data/test/storage_test.rb +191 -40
- metadata +80 -9
@@ -1,6 +1,41 @@
|
|
1
1
|
module Paperclip
|
2
2
|
module Validate
|
3
3
|
|
4
|
+
module ClassMethods
|
5
|
+
|
6
|
+
# Places ActiveRecord-style validations on the size of the file assigned. The
|
7
|
+
# possible options are:
|
8
|
+
# * +in+: a Range of bytes (i.e. +1..1.megabyte+),
|
9
|
+
# * +less_than+: equivalent to :in => 0..options[:less_than]
|
10
|
+
# * +greater_than+: equivalent to :in => options[:greater_than]..Infinity
|
11
|
+
# * +message+: error message to display, use :min and :max as replacements
|
12
|
+
def validates_attachment_size(*fields)
|
13
|
+
opts = opts_from_validator_args(fields)
|
14
|
+
add_validator_to_context(opts, fields, Paperclip::Validate::SizeValidator)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Adds errors if thumbnail creation fails. The same as specifying :whiny_thumbnails => true.
|
18
|
+
def validates_attachment_thumbnails name, options = {}
|
19
|
+
self.attachment_definitions[name][:whiny_thumbnails] = true
|
20
|
+
end
|
21
|
+
|
22
|
+
# Places ActiveRecord-style validations on the presence of a file.
|
23
|
+
def validates_attachment_presence(*fields)
|
24
|
+
opts = opts_from_validator_args(fields)
|
25
|
+
add_validator_to_context(opts, fields, Paperclip::Validate::RequiredFieldValidator)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Places ActiveRecord-style validations on the content type of the file assigned. The
|
29
|
+
# possible options are:
|
30
|
+
# * +content_type+: Allowed content types. Can be a single content type or an array. Allows all by default.
|
31
|
+
# * +message+: The message to display when the uploaded file has an invalid content type.
|
32
|
+
def validates_attachment_content_type(*fields)
|
33
|
+
opts = opts_from_validator_args(fields)
|
34
|
+
add_validator_to_context(opts, fields, Paperclip::Validate::ContentTypeValidator)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
4
39
|
class SizeValidator < DataMapper::Validate::GenericValidator #:nodoc:
|
5
40
|
def initialize(field_name, options={})
|
6
41
|
super
|
@@ -16,9 +51,9 @@ module Paperclip
|
|
16
51
|
return true if @options[:in].include? field_value.to_i
|
17
52
|
|
18
53
|
error_message ||= @options[:message] unless @options[:message].nil?
|
19
|
-
error_message ||= "%s must be less than %s bytes".t(
|
20
|
-
error_message ||= "%s must be greater than %s bytes".t(
|
21
|
-
error_message ||= "%s must be between %s and %s bytes".t(
|
54
|
+
error_message ||= "%s must be less than %s bytes".t(ActiveSupport::Inflector.humanize(@field_name), @options[:less_than]) unless @options[:less_than].nil?
|
55
|
+
error_message ||= "%s must be greater than %s bytes".t(ActiveSupport::Inflector.humanize(@field_name), @options[:greater_than]) unless @options[:greater_than].nil?
|
56
|
+
error_message ||= "%s must be between %s and %s bytes".t(ActiveSupport::Inflector.humanize(@field_name), @options[:in].first, @options[:in].last)
|
22
57
|
add_error(target, error_message , @field_name)
|
23
58
|
return false
|
24
59
|
end
|
@@ -33,7 +68,7 @@ module Paperclip
|
|
33
68
|
def call(target)
|
34
69
|
field_value = target.validation_property_value(@field_name)
|
35
70
|
if field_value.nil? || field_value.original_filename.blank?
|
36
|
-
error_message = @options[:message] || "%s must be set".t(
|
71
|
+
error_message = @options[:message] || "%s must be set".t(ActiveSupport::Inflector.humanize(@field_name))
|
37
72
|
add_error(target, error_message , @field_name)
|
38
73
|
return false
|
39
74
|
end
|
@@ -56,7 +91,7 @@ module Paperclip
|
|
56
91
|
content_type = target.validation_property_value(:"#{@field_name}_content_type")
|
57
92
|
unless valid_types.any?{|t| t === content_type }
|
58
93
|
error_message ||= @options[:message] unless @options[:message].nil?
|
59
|
-
error_message ||= "%s's content type of '%s' is not a valid content type".t(
|
94
|
+
error_message ||= "%s's content type of '%s' is not a valid content type".t(ActiveSupport::Inflector.humanize(@field_name), content_type)
|
60
95
|
add_error(target, error_message , @field_name)
|
61
96
|
return false
|
62
97
|
end
|
data/test/attachment_test.rb
CHANGED
@@ -149,9 +149,12 @@ class AttachmentTest < Test::Unit::TestCase
|
|
149
149
|
setup do
|
150
150
|
rebuild_model
|
151
151
|
|
152
|
+
@tempfile = mock
|
153
|
+
@tempfile.expects(:size).returns(10)
|
154
|
+
|
152
155
|
@not_file = mock
|
153
156
|
@not_file.stubs(:nil?).returns(false)
|
154
|
-
@not_file.expects(:to_tempfile).returns(
|
157
|
+
@not_file.expects(:to_tempfile).returns(@tempfile)
|
155
158
|
@not_file.expects(:original_filename).returns("filename.png\r\n")
|
156
159
|
@not_file.expects(:content_type).returns("image/png\r\n")
|
157
160
|
@not_file.expects(:size).returns(10)
|
@@ -178,10 +181,13 @@ class AttachmentTest < Test::Unit::TestCase
|
|
178
181
|
setup do
|
179
182
|
rebuild_model
|
180
183
|
|
184
|
+
@tempfile = mock
|
185
|
+
@tempfile.expects(:size).returns(10)
|
186
|
+
|
181
187
|
@not_file = mock
|
182
188
|
@not_file.stubs(:nil?).returns(false)
|
183
|
-
@not_file.expects(:to_tempfile).returns(
|
184
|
-
@not_file.expects(:original_filename).returns("
|
189
|
+
@not_file.expects(:to_tempfile).returns(@tempfile)
|
190
|
+
@not_file.expects(:original_filename).returns("sheep_say_b_.png\r\n")
|
185
191
|
@not_file.expects(:content_type).returns("image/png\r\n")
|
186
192
|
@not_file.expects(:size).returns(10)
|
187
193
|
|
@@ -229,12 +235,12 @@ class AttachmentTest < Test::Unit::TestCase
|
|
229
235
|
|
230
236
|
context "with a file assigned in the database" do
|
231
237
|
setup do
|
232
|
-
@instance.stubs(:
|
233
|
-
@instance.stubs(:
|
234
|
-
@instance.stubs(:
|
238
|
+
@instance.stubs(:avatar_file_name).returns('5k.png')
|
239
|
+
@instance.stubs(:avatar_content_type).returns("image/png")
|
240
|
+
@instance.stubs(:avatar_file_size).returns(12345)
|
235
241
|
@now = Time.now
|
236
242
|
Time.stubs(:now).returns(@now)
|
237
|
-
@instance.stubs(:
|
243
|
+
@instance.stubs(:avatar_updated_at).returns(Time.now)
|
238
244
|
end
|
239
245
|
|
240
246
|
should "return a correct url even if the file does not exist" do
|
@@ -257,12 +263,12 @@ class AttachmentTest < Test::Unit::TestCase
|
|
257
263
|
end
|
258
264
|
|
259
265
|
should "return the proper path when filename has a single .'s" do
|
260
|
-
assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png", @attachment.path
|
266
|
+
assert_equal File.expand_path("./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.png"), File.expand_path(@attachment.path)
|
261
267
|
end
|
262
268
|
|
263
269
|
should "return the proper path when filename has multiple .'s" do
|
264
|
-
@instance.stubs(:
|
265
|
-
assert_equal "./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.old.png", @attachment.path
|
270
|
+
@instance.stubs(:avatar_file_name).returns("5k.old.png")
|
271
|
+
assert_equal File.expand_path("./test/../tmp/avatars/dummies/original/#{@instance.id}/5k.old.png"), File.expand_path(@attachment.path)
|
266
272
|
end
|
267
273
|
|
268
274
|
context "when expecting three styles" do
|
@@ -299,7 +305,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
299
305
|
|
300
306
|
should "commit the files to disk" do
|
301
307
|
[:large, :medium, :small].each do |style|
|
302
|
-
io = @attachment.
|
308
|
+
io = @attachment.to_file(style)
|
303
309
|
assert File.exists?(io)
|
304
310
|
assert ! io.is_a?(::Tempfile)
|
305
311
|
end
|
@@ -310,7 +316,7 @@ class AttachmentTest < Test::Unit::TestCase
|
|
310
316
|
[:medium, 100, 15, "GIF"],
|
311
317
|
[:small, 32, 32, "JPEG"]].each do |style|
|
312
318
|
cmd = "identify -format '%w %h %b %m' " +
|
313
|
-
"#{@attachment.
|
319
|
+
"#{@attachment.path(style.first)}"
|
314
320
|
out = `#{cmd}`
|
315
321
|
width, height, size, format = out.split(" ")
|
316
322
|
assert_equal style[1].to_s, width.to_s
|
@@ -328,15 +334,12 @@ class AttachmentTest < Test::Unit::TestCase
|
|
328
334
|
@existing_names = @attachment.styles.keys.collect do |style|
|
329
335
|
@attachment.path(style)
|
330
336
|
end
|
331
|
-
@instance.expects(:attributes=).with({ :avatar_file_name => nil,
|
332
|
-
:avatar_content_type => nil,
|
333
|
-
:avatar_file_size => nil })
|
334
337
|
@attachment.assign nil
|
335
338
|
@attachment.save
|
336
339
|
end
|
337
340
|
|
338
341
|
should "delete the files" do
|
339
|
-
@existing_names.each{|f| assert !File.exists?(f) }
|
342
|
+
@existing_names.each { |f| assert !File.exists?(f) }
|
340
343
|
end
|
341
344
|
end
|
342
345
|
end
|
data/test/geometry_test.rb
CHANGED
@@ -62,7 +62,7 @@ class GeometryTest < Test::Unit::TestCase
|
|
62
62
|
should "make sure the modifier gets passed during transformation_to" do
|
63
63
|
assert @src = Paperclip::Geometry.parse("123x456")
|
64
64
|
assert @dst = Paperclip::Geometry.parse("123x456>")
|
65
|
-
assert_equal "123x456>", @src.transformation_to(@dst).
|
65
|
+
assert_equal "123x456>", @src.transformation_to(@dst).join
|
66
66
|
end
|
67
67
|
|
68
68
|
should "be generated from a file" do
|
data/test/helper.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
Bundler.require(:development, :runtime, :datamapper)
|
5
|
+
|
2
6
|
require 'test/unit'
|
3
7
|
require 'shoulda'
|
4
8
|
require 'mocha'
|
5
9
|
require 'tempfile'
|
6
10
|
|
11
|
+
require 'extlib'
|
7
12
|
require 'dm-core'
|
8
13
|
require 'dm-validations'
|
9
14
|
require 'dm-migrations'
|
@@ -22,7 +27,8 @@ Merb.class_eval do
|
|
22
27
|
def self.root
|
23
28
|
"#{ROOT}"
|
24
29
|
end
|
25
|
-
def self.env
|
30
|
+
def self.env(str=nil)
|
31
|
+
ENV['RAILS_ENV'] = str if str
|
26
32
|
ENV['RAILS_ENV']
|
27
33
|
end
|
28
34
|
end
|
@@ -42,6 +48,12 @@ unless defined?(Mash)
|
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
51
|
+
Paperclip.configure do |config|
|
52
|
+
config.root = Merb.root # the application root to anchor relative urls (defaults to Dir.pwd)
|
53
|
+
config.env = Merb.env # server env support, defaults to ENV['RACK_ENV'] or 'development'
|
54
|
+
config.use_dm_validations = true # validate attachment sizes and such, defaults to false
|
55
|
+
end
|
56
|
+
|
45
57
|
def rebuild_model options = {}
|
46
58
|
Object.send(:remove_const, "Dummy") rescue nil
|
47
59
|
Object.const_set("Dummy", Class.new())
|
@@ -49,7 +61,7 @@ def rebuild_model options = {}
|
|
49
61
|
include DataMapper::Resource
|
50
62
|
include DataMapper::Validate
|
51
63
|
include Paperclip::Resource
|
52
|
-
property :id,
|
64
|
+
property :id, ::DataMapper::Property::Serial
|
53
65
|
property :other, String
|
54
66
|
has_attached_file :avatar, options
|
55
67
|
end
|
@@ -57,8 +69,8 @@ def rebuild_model options = {}
|
|
57
69
|
end
|
58
70
|
|
59
71
|
def temporary_env(new_env)
|
60
|
-
old_env =
|
61
|
-
|
72
|
+
old_env = Merb.env
|
73
|
+
Merb.env(new_env)
|
62
74
|
yield
|
63
|
-
|
75
|
+
Merb.env(old_env)
|
64
76
|
end
|
data/test/iostream_test.rb
CHANGED
@@ -1,10 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'test/unit'
|
3
|
-
require 'stringio'
|
4
|
-
require 'tempfile'
|
5
|
-
require 'shoulda'
|
6
|
-
|
7
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-paperclip', 'iostream.rb')
|
1
|
+
require 'test/helper'
|
8
2
|
|
9
3
|
class IOStreamTest < Test::Unit::TestCase
|
10
4
|
context "IOStream" do
|
@@ -17,29 +11,46 @@ class IOStreamTest < Test::Unit::TestCase
|
|
17
11
|
|
18
12
|
context "A file" do
|
19
13
|
setup do
|
20
|
-
@file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"))
|
14
|
+
@file = File.new(File.join(File.dirname(__FILE__), "fixtures", "5k.png"), 'rb')
|
21
15
|
end
|
22
16
|
|
17
|
+
teardown { @file.close }
|
18
|
+
|
23
19
|
context "that is sent #stream_to" do
|
24
20
|
|
25
|
-
|
26
|
-
|
21
|
+
context "and given a String" do
|
22
|
+
setup do
|
23
|
+
FileUtils.mkdir_p(File.join(ROOT, 'tmp'))
|
24
|
+
assert @result = @file.stream_to(File.join(ROOT, 'tmp', 'iostream.string.test'))
|
25
|
+
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
27
|
+
should "return a File" do
|
28
|
+
assert @result.is_a?(File)
|
29
|
+
end
|
32
30
|
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
should "contain the same data as the original file" do
|
32
|
+
@file.rewind; @result.rewind
|
33
|
+
assert_equal @file.read, @result.read
|
34
|
+
end
|
35
|
+
end
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
37
|
+
context "and given a Tempfile" do
|
38
|
+
setup do
|
39
|
+
tempfile = Tempfile.new('iostream.test')
|
40
|
+
tempfile.binmode
|
41
|
+
assert @result = @file.stream_to(tempfile)
|
42
|
+
end
|
43
|
+
|
44
|
+
should "return a Tempfile" do
|
45
|
+
assert @result.is_a?(Tempfile)
|
46
|
+
end
|
47
|
+
|
48
|
+
should "contain the same data as the original file" do
|
49
|
+
@file.rewind; @result.rewind
|
50
|
+
assert_equal @file.read, @result.read
|
41
51
|
end
|
42
52
|
end
|
53
|
+
|
43
54
|
end
|
44
55
|
|
45
56
|
context "that is sent #to_tempfile" do
|
@@ -47,8 +58,15 @@ class IOStreamTest < Test::Unit::TestCase
|
|
47
58
|
assert @tempfile = @file.to_tempfile
|
48
59
|
end
|
49
60
|
|
50
|
-
should "convert it to a Tempfile" do
|
51
|
-
assert @tempfile.is_a?(Tempfile)
|
61
|
+
should "convert it to a Paperclip Tempfile" do
|
62
|
+
assert @tempfile.is_a?(Paperclip::Tempfile)
|
63
|
+
end
|
64
|
+
|
65
|
+
should "have the name be based on the original_filename" do
|
66
|
+
name = File.basename(@file.path)
|
67
|
+
extension = File.extname(name)
|
68
|
+
basename = File.basename(name, extension)
|
69
|
+
assert_match %r[^#{Regexp.quote(basename)}.*?#{Regexp.quote(extension)}], File.basename(@tempfile.path)
|
52
70
|
end
|
53
71
|
|
54
72
|
should "have the Tempfile contain the same data as the file" do
|
@@ -57,4 +75,4 @@ class IOStreamTest < Test::Unit::TestCase
|
|
57
75
|
end
|
58
76
|
end
|
59
77
|
end
|
60
|
-
end
|
78
|
+
end
|
data/test/paperclip_test.rb
CHANGED
@@ -21,7 +21,7 @@ class PaperclipTest < Test::Unit::TestCase
|
|
21
21
|
include DataMapper::Resource
|
22
22
|
include DataMapper::Validate
|
23
23
|
include Paperclip::Resource
|
24
|
-
property :id,
|
24
|
+
property :id, ::DataMapper::Property::Serial
|
25
25
|
property :other, String
|
26
26
|
has_attached_file :file
|
27
27
|
end
|
data/test/storage_test.rb
CHANGED
@@ -1,13 +1,10 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
require 'shoulda'
|
4
|
-
require 'right_aws'
|
5
|
-
|
6
|
-
require File.join(File.dirname(__FILE__), '..', 'lib', 'dm-paperclip', 'geometry.rb')
|
1
|
+
require 'test/helper'
|
2
|
+
require 'aws/s3'
|
7
3
|
|
8
4
|
class StorageTest < Test::Unit::TestCase
|
9
5
|
context "Parsing S3 credentials" do
|
10
6
|
setup do
|
7
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
11
8
|
rebuild_model :storage => :s3,
|
12
9
|
:bucket => "testing",
|
13
10
|
:s3_credentials => {:not => :important}
|
@@ -15,48 +12,133 @@ class StorageTest < Test::Unit::TestCase
|
|
15
12
|
@dummy = Dummy.new
|
16
13
|
@avatar = @dummy.avatar
|
17
14
|
|
18
|
-
@current_env =
|
15
|
+
@current_env = Merb.env
|
19
16
|
end
|
20
17
|
|
21
18
|
teardown do
|
22
|
-
|
19
|
+
Merb.env(@current_env)
|
23
20
|
end
|
24
21
|
|
25
|
-
should "get the correct credentials when
|
26
|
-
|
27
|
-
assert_equal({
|
22
|
+
should "get the correct credentials when environment is production" do
|
23
|
+
Merb.env("production")
|
24
|
+
assert_equal({:key => "12345"},
|
28
25
|
@avatar.parse_credentials('production' => {:key => '12345'},
|
29
26
|
:development => {:key => "54321"}))
|
30
27
|
end
|
31
28
|
|
32
|
-
should "get the correct credentials when
|
33
|
-
|
34
|
-
assert_equal({
|
29
|
+
should "get the correct credentials when environment is development" do
|
30
|
+
Merb.env("development")
|
31
|
+
assert_equal({:key => "54321"},
|
35
32
|
@avatar.parse_credentials('production' => {:key => '12345'},
|
36
33
|
:development => {:key => "54321"}))
|
37
34
|
end
|
38
35
|
|
39
36
|
should "return the argument if the key does not exist" do
|
40
|
-
|
41
|
-
assert_equal({
|
37
|
+
Merb.env("not really an env")
|
38
|
+
assert_equal({:test => "12345"}, @avatar.parse_credentials(:test => "12345"))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "" do
|
43
|
+
setup do
|
44
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
45
|
+
rebuild_model :storage => :s3,
|
46
|
+
:s3_credentials => {},
|
47
|
+
:bucket => "bucket",
|
48
|
+
:path => ":attachment/:basename.:extension",
|
49
|
+
:url => ":s3_path_url"
|
50
|
+
@dummy = Dummy.new
|
51
|
+
@dummy.avatar = StringIO.new(".")
|
52
|
+
end
|
53
|
+
|
54
|
+
should "return a url based on an S3 path" do
|
55
|
+
assert_match %r{^http://s3.amazonaws.com/bucket/avatars/stringio.txt}, @dummy.avatar.url
|
56
|
+
end
|
57
|
+
end
|
58
|
+
context "" do
|
59
|
+
setup do
|
60
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
61
|
+
rebuild_model :storage => :s3,
|
62
|
+
:s3_credentials => {},
|
63
|
+
:bucket => "bucket",
|
64
|
+
:path => ":attachment/:basename.:extension",
|
65
|
+
:url => ":s3_domain_url"
|
66
|
+
@dummy = Dummy.new
|
67
|
+
@dummy.avatar = StringIO.new(".")
|
68
|
+
end
|
69
|
+
|
70
|
+
should "return a url based on an S3 subdomain" do
|
71
|
+
assert_match %r{^http://bucket.s3.amazonaws.com/avatars/stringio.txt}, @dummy.avatar.url
|
72
|
+
end
|
73
|
+
end
|
74
|
+
context "" do
|
75
|
+
setup do
|
76
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
77
|
+
rebuild_model :storage => :s3,
|
78
|
+
:s3_credentials => {
|
79
|
+
:production => { :bucket => "prod_bucket" },
|
80
|
+
:development => { :bucket => "dev_bucket" }
|
81
|
+
},
|
82
|
+
:s3_host_alias => "something.something.com",
|
83
|
+
:path => ":attachment/:basename.:extension",
|
84
|
+
:url => ":s3_alias_url"
|
85
|
+
@dummy = Dummy.new
|
86
|
+
@dummy.avatar = StringIO.new(".")
|
87
|
+
end
|
88
|
+
|
89
|
+
should "return a url based on the host_alias" do
|
90
|
+
assert_match %r{^http://something.something.com/avatars/stringio.txt}, @dummy.avatar.url
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
context "Generating a url with an expiration" do
|
95
|
+
setup do
|
96
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
97
|
+
rebuild_model :storage => :s3,
|
98
|
+
:s3_credentials => {
|
99
|
+
:production => { :bucket => "prod_bucket" },
|
100
|
+
:development => { :bucket => "dev_bucket" }
|
101
|
+
},
|
102
|
+
:s3_host_alias => "something.something.com",
|
103
|
+
:path => ":attachment/:basename.:extension",
|
104
|
+
:url => ":s3_alias_url"
|
105
|
+
|
106
|
+
Merb.env("production")
|
107
|
+
|
108
|
+
@dummy = Dummy.new
|
109
|
+
@dummy.avatar = StringIO.new(".")
|
110
|
+
|
111
|
+
AWS::S3::S3Object.expects(:url_for).with("avatars/stringio.txt", "prod_bucket", { :expires_in => 3600 })
|
112
|
+
|
113
|
+
@dummy.avatar.expiring_url
|
114
|
+
end
|
115
|
+
|
116
|
+
should "should succeed" do
|
117
|
+
assert true
|
42
118
|
end
|
43
119
|
end
|
44
120
|
|
45
121
|
context "Parsing S3 credentials with a bucket in them" do
|
46
122
|
setup do
|
123
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
47
124
|
rebuild_model :storage => :s3,
|
48
125
|
:s3_credentials => {
|
49
126
|
:production => { :bucket => "prod_bucket" },
|
50
127
|
:development => { :bucket => "dev_bucket" }
|
51
128
|
}
|
52
129
|
@dummy = Dummy.new
|
130
|
+
@old_env = Merb.env
|
53
131
|
end
|
54
132
|
|
55
|
-
|
133
|
+
teardown{ Merb.env(@old_env) }
|
134
|
+
|
135
|
+
should "get the right bucket in production" do
|
136
|
+
Merb.env("production")
|
56
137
|
assert_equal "prod_bucket", @dummy.avatar.bucket_name
|
57
138
|
end
|
58
139
|
|
59
|
-
should "get the right bucket in development"
|
140
|
+
should "get the right bucket in development" do
|
141
|
+
Merb.env("development")
|
60
142
|
assert_equal "dev_bucket", @dummy.avatar.bucket_name
|
61
143
|
end
|
62
144
|
end
|
@@ -82,11 +164,13 @@ class StorageTest < Test::Unit::TestCase
|
|
82
164
|
|
83
165
|
context "when assigned" do
|
84
166
|
setup do
|
85
|
-
@file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'))
|
167
|
+
@file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
|
86
168
|
@dummy = Dummy.new
|
87
169
|
@dummy.avatar = @file
|
88
170
|
end
|
89
171
|
|
172
|
+
teardown { @file.close }
|
173
|
+
|
90
174
|
should "not get a bucket to get a URL" do
|
91
175
|
@dummy.avatar.expects(:s3).never
|
92
176
|
@dummy.avatar.expects(:s3_bucket).never
|
@@ -95,15 +179,7 @@ class StorageTest < Test::Unit::TestCase
|
|
95
179
|
|
96
180
|
context "and saved" do
|
97
181
|
setup do
|
98
|
-
@
|
99
|
-
@bucket_mock = stub
|
100
|
-
RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
|
101
|
-
@s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
|
102
|
-
@key_mock = stub
|
103
|
-
@bucket_mock.expects(:key).returns(@key_mock)
|
104
|
-
@key_mock.expects(:data=)
|
105
|
-
@key_mock.expects(:put)
|
106
|
-
@dummy.id = 1
|
182
|
+
AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path, anything, 'testing', :content_type => 'image/png', :access => :public_read)
|
107
183
|
@dummy.save
|
108
184
|
end
|
109
185
|
|
@@ -114,13 +190,8 @@ class StorageTest < Test::Unit::TestCase
|
|
114
190
|
|
115
191
|
context "and remove" do
|
116
192
|
setup do
|
117
|
-
|
118
|
-
|
119
|
-
RightAws::S3.expects(:new).with("12345", "54321", {}).returns(@s3_mock)
|
120
|
-
@s3_mock.expects(:bucket).with("testing", true, "public-read").returns(@bucket_mock)
|
121
|
-
@key_mock = stub
|
122
|
-
@bucket_mock.expects(:key).at_least(2).returns(@key_mock)
|
123
|
-
@key_mock.expects(:delete)
|
193
|
+
AWS::S3::S3Object.stubs(:exists?).returns(true)
|
194
|
+
AWS::S3::S3Object.stubs(:delete)
|
124
195
|
@dummy.destroy_attached_files
|
125
196
|
end
|
126
197
|
|
@@ -130,6 +201,84 @@ class StorageTest < Test::Unit::TestCase
|
|
130
201
|
end
|
131
202
|
end
|
132
203
|
end
|
204
|
+
|
205
|
+
context "An attachment with S3 storage and bucket defined as a Proc" do
|
206
|
+
setup do
|
207
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
208
|
+
rebuild_model :storage => :s3,
|
209
|
+
:bucket => lambda { |attachment| "bucket_#{attachment.instance.other}" },
|
210
|
+
:s3_credentials => {:not => :important}
|
211
|
+
end
|
212
|
+
|
213
|
+
should "get the right bucket name" do
|
214
|
+
assert "bucket_a", Dummy.new(:other => 'a').avatar.bucket_name
|
215
|
+
assert "bucket_b", Dummy.new(:other => 'b').avatar.bucket_name
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
context "An attachment with S3 storage and specific s3 headers set" do
|
220
|
+
setup do
|
221
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
222
|
+
rebuild_model :storage => :s3,
|
223
|
+
:bucket => "testing",
|
224
|
+
:path => ":attachment/:style/:basename.:extension",
|
225
|
+
:s3_credentials => {
|
226
|
+
'access_key_id' => "12345",
|
227
|
+
'secret_access_key' => "54321"
|
228
|
+
},
|
229
|
+
:s3_headers => {'Cache-Control' => 'max-age=31557600'}
|
230
|
+
end
|
231
|
+
|
232
|
+
context "when assigned" do
|
233
|
+
setup do
|
234
|
+
@file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
|
235
|
+
@dummy = Dummy.new
|
236
|
+
@dummy.avatar = @file
|
237
|
+
end
|
238
|
+
|
239
|
+
teardown { @file.close }
|
240
|
+
|
241
|
+
context "and saved" do
|
242
|
+
setup do
|
243
|
+
AWS::S3::Base.stubs(:establish_connection!)
|
244
|
+
AWS::S3::S3Object.stubs(:store).with(@dummy.avatar.path,
|
245
|
+
anything,
|
246
|
+
'testing',
|
247
|
+
:content_type => 'image/png',
|
248
|
+
:access => :public_read,
|
249
|
+
'Cache-Control' => 'max-age=31557600')
|
250
|
+
@dummy.save
|
251
|
+
end
|
252
|
+
|
253
|
+
should "succeed" do
|
254
|
+
assert true
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
context "with S3 credentials in a YAML file" do
|
261
|
+
setup do
|
262
|
+
ENV['S3_KEY'] = 'env_key'
|
263
|
+
ENV['S3_BUCKET'] = 'env_bucket'
|
264
|
+
ENV['S3_SECRET'] = 'env_secret'
|
265
|
+
|
266
|
+
Merb.env('test')
|
267
|
+
|
268
|
+
rebuild_model :storage => :s3,
|
269
|
+
:s3_credentials => File.new(File.join(File.dirname(__FILE__), "fixtures/s3.yml"))
|
270
|
+
|
271
|
+
Dummy.auto_migrate!
|
272
|
+
|
273
|
+
@dummy = Dummy.new
|
274
|
+
end
|
275
|
+
|
276
|
+
should "run it the file through ERB" do
|
277
|
+
assert_equal 'env_bucket', @dummy.avatar.bucket_name
|
278
|
+
assert_equal 'env_key', AWS::S3::Base.connection.options[:access_key_id]
|
279
|
+
assert_equal 'env_secret', AWS::S3::Base.connection.options[:secret_access_key]
|
280
|
+
end
|
281
|
+
end
|
133
282
|
|
134
283
|
unless ENV["S3_TEST_BUCKET"].blank?
|
135
284
|
context "Using S3 for real, an attachment with S3 storage" do
|
@@ -140,7 +289,7 @@ class StorageTest < Test::Unit::TestCase
|
|
140
289
|
:path => ":class/:attachment/:id/:style.:extension",
|
141
290
|
:s3_credentials => File.new(File.join(File.dirname(__FILE__), "s3.yml"))
|
142
291
|
|
143
|
-
Dummy.
|
292
|
+
Dummy.auto_migrate!
|
144
293
|
@dummy = Dummy.new
|
145
294
|
end
|
146
295
|
|
@@ -150,12 +299,14 @@ class StorageTest < Test::Unit::TestCase
|
|
150
299
|
|
151
300
|
context "when assigned" do
|
152
301
|
setup do
|
153
|
-
@file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'))
|
302
|
+
@file = File.new(File.join(File.dirname(__FILE__), 'fixtures', '5k.png'), 'rb')
|
154
303
|
@dummy.avatar = @file
|
155
304
|
end
|
156
305
|
|
157
|
-
|
158
|
-
|
306
|
+
teardown { @file.close }
|
307
|
+
|
308
|
+
should "still return a Tempfile when sent #to_file" do
|
309
|
+
assert_equal Tempfile, @dummy.avatar.to_file.class
|
159
310
|
end
|
160
311
|
|
161
312
|
context "and saved" do
|
@@ -170,4 +321,4 @@ class StorageTest < Test::Unit::TestCase
|
|
170
321
|
end
|
171
322
|
end
|
172
323
|
end
|
173
|
-
end
|
324
|
+
end
|