jnicklas-carrierwave 0.1.1 → 0.2.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.
- data/LICENSE +1 -1
- data/{README.md → README.rdoc} +63 -78
- data/Rakefile +12 -6
- data/lib/carrierwave/mount.rb +133 -52
- data/lib/carrierwave/orm/activerecord.rb +52 -3
- data/lib/carrierwave/orm/datamapper.rb +5 -2
- data/lib/carrierwave/orm/sequel.rb +23 -0
- data/lib/carrierwave/processing/image_science.rb +3 -3
- data/lib/carrierwave/processing/rmagick.rb +103 -47
- data/lib/carrierwave/sanitized_file.rb +71 -45
- data/lib/carrierwave/storage/abstract.rb +23 -9
- data/lib/carrierwave/storage/file.rb +17 -9
- data/lib/carrierwave/storage/s3.rb +49 -22
- data/lib/carrierwave/test/matchers.rb +112 -0
- data/lib/carrierwave/uploader.rb +231 -112
- data/lib/carrierwave.rb +32 -17
- data/lib/generators/uploader_generator.rb +7 -7
- data/rails_generators/uploader/templates/uploader.rb +9 -1
- data/spec/mount_spec.rb +147 -3
- data/spec/orm/activerecord_spec.rb +24 -3
- data/spec/orm/datamapper_spec.rb +3 -3
- data/spec/orm/sequel_spec.rb +170 -0
- data/spec/sanitized_file_spec.rb +22 -36
- data/spec/spec_helper.rb +44 -80
- data/spec/uploader_spec.rb +86 -22
- metadata +8 -4
@@ -17,21 +17,20 @@ module CarrierWave
|
|
17
17
|
# Possible values are the 'canned access control policies' provided in the aws/s3 gem,
|
18
18
|
# they are:
|
19
19
|
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
20
|
+
# [:private] No one else has any access rights.
|
21
|
+
# [:public_read] The anonymous principal is granted READ access.
|
22
|
+
# If this policy is used on an object, it can be read from a
|
23
|
+
# browser with no authentication.
|
24
|
+
# [:public_read_write] The anonymous principal is granted READ and WRITE access.
|
25
|
+
# [:authenticated_read] Any principal authenticated as a registered Amazon S3 user
|
26
|
+
# is granted READ access.
|
27
27
|
#
|
28
28
|
# The default is :public_read, it should work in most cases.
|
29
29
|
#
|
30
30
|
class S3 < Abstract
|
31
31
|
|
32
|
-
def initialize(
|
33
|
-
@
|
34
|
-
@store_dir = store_dir
|
32
|
+
def initialize(store_path, identifier)
|
33
|
+
@store_path = store_path
|
35
34
|
@identifier = identifier
|
36
35
|
end
|
37
36
|
|
@@ -47,14 +46,18 @@ module CarrierWave
|
|
47
46
|
end
|
48
47
|
|
49
48
|
##
|
50
|
-
#
|
49
|
+
# === Returns
|
50
|
+
#
|
51
|
+
# [String] the bucket set in the config options
|
51
52
|
#
|
52
53
|
def self.bucket
|
53
54
|
CarrierWave.config[:s3][:bucket]
|
54
55
|
end
|
55
56
|
|
56
57
|
##
|
57
|
-
#
|
58
|
+
# === Returns
|
59
|
+
#
|
60
|
+
# [Symbol] the access priviliges the uploaded files should have
|
58
61
|
#
|
59
62
|
def self.access
|
60
63
|
CarrierWave.config[:s3][:access]
|
@@ -63,14 +66,18 @@ module CarrierWave
|
|
63
66
|
##
|
64
67
|
# Store the file on S3
|
65
68
|
#
|
66
|
-
#
|
67
|
-
#
|
69
|
+
# === Parameters
|
70
|
+
#
|
71
|
+
# [uploader (CarrierWave::Uploader)] an uploader object
|
72
|
+
# [file (CarrierWave::SanitizedFile)] the file to store
|
68
73
|
#
|
69
|
-
#
|
74
|
+
# === Returns
|
75
|
+
#
|
76
|
+
# [CarrierWave::Storage::S3] the stored file
|
70
77
|
#
|
71
78
|
def self.store!(uploader, file)
|
72
|
-
AWS::S3::S3Object.store(::File.join(uploader.
|
73
|
-
self.new(
|
79
|
+
AWS::S3::S3Object.store(::File.join(uploader.store_path), file.read, bucket, :access => access)
|
80
|
+
self.new(uploader.store_dir, uploader.filename)
|
74
81
|
end
|
75
82
|
|
76
83
|
# Do something to retrieve the file
|
@@ -78,28 +85,48 @@ module CarrierWave
|
|
78
85
|
# @param [CarrierWave::Uploader] uploader an uploader object
|
79
86
|
# @param [String] identifier uniquely identifies the file
|
80
87
|
#
|
81
|
-
#
|
88
|
+
# [uploader (CarrierWave::Uploader)] an uploader object
|
89
|
+
# [identifier (String)] uniquely identifies the file
|
90
|
+
#
|
91
|
+
# === Returns
|
92
|
+
#
|
93
|
+
# [CarrierWave::Storage::S3] the stored file
|
82
94
|
#
|
83
95
|
def self.retrieve!(uploader, identifier)
|
84
|
-
self.new(
|
96
|
+
self.new(uploader.store_path(identifier), identifier)
|
85
97
|
end
|
86
98
|
|
87
99
|
##
|
88
100
|
# Returns the filename on S3
|
89
101
|
#
|
90
|
-
#
|
102
|
+
# === Returns
|
103
|
+
#
|
104
|
+
# [String] path to the file
|
91
105
|
#
|
92
106
|
def identifier
|
93
107
|
@identifier
|
94
108
|
end
|
95
109
|
|
110
|
+
##
|
111
|
+
# Reads the contents of the file from S3
|
112
|
+
#
|
113
|
+
# === Returns
|
114
|
+
#
|
115
|
+
# [String] contents of the file
|
116
|
+
#
|
117
|
+
def read
|
118
|
+
S3Object.value @store_path, self.class.bucket
|
119
|
+
end
|
120
|
+
|
96
121
|
##
|
97
122
|
# Returns the url on Amazon's S3 service
|
98
123
|
#
|
99
|
-
#
|
124
|
+
# === Returns
|
125
|
+
#
|
126
|
+
# [String] file's url
|
100
127
|
#
|
101
128
|
def url
|
102
|
-
["http://s3.amazonaws.com", self.class.bucket, @
|
129
|
+
["http://s3.amazonaws.com", self.class.bucket, @store_path].compact.join('/')
|
103
130
|
end
|
104
131
|
|
105
132
|
end # S3
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
module Test
|
3
|
+
|
4
|
+
##
|
5
|
+
# These are some matchers that can be used in RSpec specs, to simplify the testing
|
6
|
+
# of uploaders.
|
7
|
+
#
|
8
|
+
module Matchers
|
9
|
+
|
10
|
+
class BeIdenticalTo
|
11
|
+
def initialize(expected)
|
12
|
+
@expected = expected
|
13
|
+
end
|
14
|
+
def matches?(actual)
|
15
|
+
@actual = actual
|
16
|
+
FileUtils.identical?(@actual, @expected)
|
17
|
+
end
|
18
|
+
def failure_message
|
19
|
+
"expected #{@actual.inspect} to be identical to #{@expected.inspect}"
|
20
|
+
end
|
21
|
+
def negative_failure_message
|
22
|
+
"expected #{@actual.inspect} to not be identical to #{@expected.inspect}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def be_identical_to(expected)
|
27
|
+
BeIdenticalTo.new(expected)
|
28
|
+
end
|
29
|
+
|
30
|
+
class HavePermissions
|
31
|
+
def initialize(expected)
|
32
|
+
@expected = expected
|
33
|
+
end
|
34
|
+
|
35
|
+
def matches?(actual)
|
36
|
+
@actual = actual
|
37
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
38
|
+
(File.stat(@actual.path).mode & 0777) == @expected
|
39
|
+
end
|
40
|
+
|
41
|
+
def failure_message
|
42
|
+
"expected #{@actual.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
|
43
|
+
end
|
44
|
+
|
45
|
+
def negative_failure_message
|
46
|
+
"expected #{@actual.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def have_permissions(expected)
|
51
|
+
HavePermissions.new(expected)
|
52
|
+
end
|
53
|
+
|
54
|
+
class BeNoLargerThan
|
55
|
+
def initialize(width, height)
|
56
|
+
@width, @height = width, height
|
57
|
+
end
|
58
|
+
|
59
|
+
def matches?(actual)
|
60
|
+
@actual = actual
|
61
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
62
|
+
require 'RMagick'
|
63
|
+
img = ::Magick::Image.read(@actual.path).first
|
64
|
+
@actual_width = img.columns
|
65
|
+
@actual_height = img.rows
|
66
|
+
@actual_width <= @width && @actual_height <= @height
|
67
|
+
end
|
68
|
+
|
69
|
+
def failure_message
|
70
|
+
"expected #{@actual.inspect} to be no larger than #{@width} by #{@height}, but it was #{@actual_height} by #{@actual_width}."
|
71
|
+
end
|
72
|
+
|
73
|
+
def negative_failure_message
|
74
|
+
"expected #{@actual.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def be_no_larger_than(width, height)
|
79
|
+
BeNoLargerThan.new(width, height)
|
80
|
+
end
|
81
|
+
|
82
|
+
class HaveDimensions
|
83
|
+
def initialize(width, height)
|
84
|
+
@width, @height = width, height
|
85
|
+
end
|
86
|
+
|
87
|
+
def matches?(actual)
|
88
|
+
@actual = actual
|
89
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
90
|
+
require 'RMagick'
|
91
|
+
img = ::Magick::Image.read(@actual.path).first
|
92
|
+
@actual_width = img.columns
|
93
|
+
@actual_height = img.rows
|
94
|
+
@actual_width == @width && @actual_height == @height
|
95
|
+
end
|
96
|
+
|
97
|
+
def failure_message
|
98
|
+
"expected #{@actual.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@actual_height} by #{@actual_width}."
|
99
|
+
end
|
100
|
+
|
101
|
+
def negative_failure_message
|
102
|
+
"expected #{@actual.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def have_dimensions(width, height)
|
107
|
+
HaveDimensions.new(width, height)
|
108
|
+
end
|
109
|
+
|
110
|
+
end # SpecHelper
|
111
|
+
end # Test
|
112
|
+
end # CarrierWave
|