thorsson_carrierwave 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Generators +4 -0
- data/History.txt +125 -0
- data/Manifest.txt +111 -0
- data/README.rdoc +528 -0
- data/Rakefile +39 -0
- data/cucumber.yml +2 -0
- data/features/caching.feature +28 -0
- data/features/download.feature +20 -0
- data/features/file_storage.feature +37 -0
- data/features/file_storage_overridden_filename.feature +38 -0
- data/features/file_storage_overridden_store_dir.feature +38 -0
- data/features/file_storage_reversing_processor.feature +43 -0
- data/features/fixtures/bork.txt +1 -0
- data/features/fixtures/monkey.txt +1 -0
- data/features/grid_fs_storage.feature +32 -0
- data/features/mount_activerecord.feature +46 -0
- data/features/mount_datamapper.feature +46 -0
- data/features/step_definitions/activerecord_steps.rb +22 -0
- data/features/step_definitions/caching_steps.rb +14 -0
- data/features/step_definitions/datamapper_steps.rb +29 -0
- data/features/step_definitions/download_steps.rb +4 -0
- data/features/step_definitions/file_steps.rb +53 -0
- data/features/step_definitions/general_steps.rb +85 -0
- data/features/step_definitions/mount_steps.rb +19 -0
- data/features/step_definitions/store_steps.rb +18 -0
- data/features/support/activerecord.rb +30 -0
- data/features/support/datamapper.rb +7 -0
- data/features/support/env.rb +22 -0
- data/features/versions_basics.feature +50 -0
- data/features/versions_nested_versions.feature +70 -0
- data/features/versions_overridden_filename.feature +51 -0
- data/features/versions_overriden_store_dir.feature +41 -0
- data/lib/carrierwave/compatibility/paperclip.rb +95 -0
- data/lib/carrierwave/core_ext/blank.rb +46 -0
- data/lib/carrierwave/core_ext/inheritable_attributes.rb +104 -0
- data/lib/carrierwave/core_ext/module_setup.rb +51 -0
- data/lib/carrierwave/mount.rb +359 -0
- data/lib/carrierwave/orm/activerecord.rb +73 -0
- data/lib/carrierwave/orm/datamapper.rb +27 -0
- data/lib/carrierwave/orm/mongoid.rb +23 -0
- data/lib/carrierwave/orm/mongomapper.rb +27 -0
- data/lib/carrierwave/orm/sequel.rb +45 -0
- data/lib/carrierwave/processing/image_science.rb +101 -0
- data/lib/carrierwave/processing/mini_magick.rb +265 -0
- data/lib/carrierwave/processing/rmagick.rb +282 -0
- data/lib/carrierwave/sanitized_file.rb +273 -0
- data/lib/carrierwave/storage/abstract.rb +30 -0
- data/lib/carrierwave/storage/cloud_files.rb +169 -0
- data/lib/carrierwave/storage/file.rb +48 -0
- data/lib/carrierwave/storage/grid_fs.rb +97 -0
- data/lib/carrierwave/storage/right_s3.rb +167 -0
- data/lib/carrierwave/storage/s3.rb +199 -0
- data/lib/carrierwave/test/matchers.rb +128 -0
- data/lib/carrierwave/uploader/cache.rb +145 -0
- data/lib/carrierwave/uploader/callbacks.rb +42 -0
- data/lib/carrierwave/uploader/configuration.rb +130 -0
- data/lib/carrierwave/uploader/default_url.rb +19 -0
- data/lib/carrierwave/uploader/download.rb +59 -0
- data/lib/carrierwave/uploader/extension_whitelist.rb +37 -0
- data/lib/carrierwave/uploader/mountable.rb +39 -0
- data/lib/carrierwave/uploader/processing.rb +83 -0
- data/lib/carrierwave/uploader/proxy.rb +62 -0
- data/lib/carrierwave/uploader/remove.rb +22 -0
- data/lib/carrierwave/uploader/store.rb +89 -0
- data/lib/carrierwave/uploader/url.rb +33 -0
- data/lib/carrierwave/uploader/versions.rb +146 -0
- data/lib/carrierwave/uploader.rb +44 -0
- data/lib/carrierwave.rb +99 -0
- data/merb_generators/uploader_generator.rb +22 -0
- data/rails_generators/uploader/USAGE +2 -0
- data/rails_generators/uploader/templates/uploader.rb +47 -0
- data/rails_generators/uploader/uploader_generator.rb +21 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/compatibility/paperclip_spec.rb +52 -0
- data/spec/fixtures/bork.txt +1 -0
- data/spec/fixtures/landscape.jpg +0 -0
- data/spec/fixtures/portrait.jpg +0 -0
- data/spec/fixtures/test.jpeg +1 -0
- data/spec/fixtures/test.jpg +1 -0
- data/spec/mount_spec.rb +538 -0
- data/spec/orm/activerecord_spec.rb +271 -0
- data/spec/orm/datamapper_spec.rb +168 -0
- data/spec/orm/mongoid_spec.rb +202 -0
- data/spec/orm/mongomapper_spec.rb +202 -0
- data/spec/orm/sequel_spec.rb +183 -0
- data/spec/processing/image_science_spec.rb +56 -0
- data/spec/processing/mini_magick_spec.rb +76 -0
- data/spec/processing/rmagick_spec.rb +75 -0
- data/spec/sanitized_file_spec.rb +623 -0
- data/spec/spec_helper.rb +92 -0
- data/spec/storage/grid_fs_spec.rb +83 -0
- data/spec/storage/right_s3_spec.rb +83 -0
- data/spec/storage/s3_spec.rb +95 -0
- data/spec/uploader/cache_spec.rb +209 -0
- data/spec/uploader/configuration_spec.rb +105 -0
- data/spec/uploader/default_url_spec.rb +85 -0
- data/spec/uploader/download_spec.rb +75 -0
- data/spec/uploader/extension_whitelist_spec.rb +44 -0
- data/spec/uploader/mountable_spec.rb +33 -0
- data/spec/uploader/paths_spec.rb +22 -0
- data/spec/uploader/processing_spec.rb +73 -0
- data/spec/uploader/proxy_spec.rb +54 -0
- data/spec/uploader/remove_spec.rb +70 -0
- data/spec/uploader/store_spec.rb +264 -0
- data/spec/uploader/url_spec.rb +102 -0
- data/spec/uploader/versions_spec.rb +298 -0
- metadata +436 -0
@@ -0,0 +1,199 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'aws/s3'
|
3
|
+
|
4
|
+
module CarrierWave
|
5
|
+
module Storage
|
6
|
+
|
7
|
+
##
|
8
|
+
# Uploads things to Amazon S3 webservices. It requies the aws/s3 gem. In order for
|
9
|
+
# CarrierWave to connect to Amazon S3, you'll need to specify an access key id, secret key
|
10
|
+
# and bucket:
|
11
|
+
#
|
12
|
+
# CarrierWave.configure do |config|
|
13
|
+
# config.s3_access_key_id = "xxxxxx"
|
14
|
+
# config.s3_secret_access_key = "xxxxxx"
|
15
|
+
# config.s3_bucket = "my_bucket_name"
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# You can also set the access policy for the uploaded files:
|
19
|
+
#
|
20
|
+
# CarrierWave.configure do |config|
|
21
|
+
# config.s3_access = :public
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# Possible values are the 'canned access control policies' provided in the aws/s3 gem,
|
25
|
+
# they are:
|
26
|
+
#
|
27
|
+
# [:private] No one else has any access rights.
|
28
|
+
# [:public_read] The anonymous principal is granted READ access.
|
29
|
+
# If this policy is used on an object, it can be read from a
|
30
|
+
# browser with no authentication.
|
31
|
+
# [:public_read_write] The anonymous principal is granted READ and WRITE access.
|
32
|
+
# [:authenticated_read] Any principal authenticated as a registered Amazon S3 user
|
33
|
+
# is granted READ access.
|
34
|
+
#
|
35
|
+
# The default is :public_read, it should work in most cases.
|
36
|
+
#
|
37
|
+
# You can assign HTTP headers to be used when S3 serves your files:
|
38
|
+
#
|
39
|
+
# CarrierWave.configure do |config|
|
40
|
+
# config.s3_headers = {"Content-Disposition" => "attachment; filename=foo.jpg;"}
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# You can also set the headers dynamically by overriding the s3_headers method:
|
44
|
+
#
|
45
|
+
# class MyUploader < CarrierWave::Uploader::Base
|
46
|
+
# def s3_headers
|
47
|
+
# { "Expires" => 1.year.from_how.httpdate }
|
48
|
+
# end
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# You can change the generated url to a cnamed domain by setting the cnamed config:
|
52
|
+
#
|
53
|
+
# CarrierWave.configure do |config|
|
54
|
+
# config.s3_cnamed = true
|
55
|
+
# config.s3_bucket = 'bucketname.domain.tld'
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# Now the resulting url will be
|
59
|
+
#
|
60
|
+
# http://bucketname.domain.tld/path/to/file
|
61
|
+
#
|
62
|
+
# instead of
|
63
|
+
#
|
64
|
+
# http://s3.amazonaws.com/bucketname.domain.tld/path/to/file
|
65
|
+
#
|
66
|
+
class S3 < Abstract
|
67
|
+
|
68
|
+
class File
|
69
|
+
|
70
|
+
def initialize(uploader, path)
|
71
|
+
@uploader = uploader
|
72
|
+
@path = path
|
73
|
+
end
|
74
|
+
|
75
|
+
##
|
76
|
+
# Returns the current path of the file on S3
|
77
|
+
#
|
78
|
+
# === Returns
|
79
|
+
#
|
80
|
+
# [String] A path
|
81
|
+
#
|
82
|
+
def path
|
83
|
+
@path
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Reads the contents of the file from S3
|
88
|
+
#
|
89
|
+
# === Returns
|
90
|
+
#
|
91
|
+
# [String] contents of the file
|
92
|
+
#
|
93
|
+
def read
|
94
|
+
AWS::S3::S3Object.value @path, @uploader.s3_bucket
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Remove the file from Amazon S3
|
99
|
+
#
|
100
|
+
def delete
|
101
|
+
AWS::S3::S3Object.delete @path, @uploader.s3_bucket
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Returns the url on Amazon's S3 service
|
106
|
+
#
|
107
|
+
# === Returns
|
108
|
+
#
|
109
|
+
# [String] file's url
|
110
|
+
#
|
111
|
+
def url
|
112
|
+
if @uploader.s3_cnamed
|
113
|
+
["http://", @uploader.s3_bucket, "/", @path].compact.join
|
114
|
+
else
|
115
|
+
["http://s3.amazonaws.com/", @uploader.s3_bucket, "/", @path].compact.join
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def about
|
120
|
+
s3_object.about
|
121
|
+
end
|
122
|
+
|
123
|
+
def metadata
|
124
|
+
s3_object.metadata
|
125
|
+
end
|
126
|
+
|
127
|
+
def content_type
|
128
|
+
s3_object.content_type
|
129
|
+
end
|
130
|
+
|
131
|
+
def content_type=(new_content_type)
|
132
|
+
s3_object.content_type = new_content_type
|
133
|
+
end
|
134
|
+
|
135
|
+
def content_disposition
|
136
|
+
s3_object.content_disposition
|
137
|
+
end
|
138
|
+
|
139
|
+
def content_disposition=(new_disposition)
|
140
|
+
s3_object.content_disposition = new_disposition
|
141
|
+
end
|
142
|
+
|
143
|
+
def store
|
144
|
+
s3_object.store
|
145
|
+
end
|
146
|
+
|
147
|
+
def s3_object
|
148
|
+
@s3_object ||= AWS::S3::S3Object.find(@path, @uploader.s3_bucket)
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Store the file on S3
|
155
|
+
#
|
156
|
+
# === Parameters
|
157
|
+
#
|
158
|
+
# [file (CarrierWave::Storage::S3::File)] the file to store
|
159
|
+
#
|
160
|
+
# === Returns
|
161
|
+
#
|
162
|
+
# [CarrierWave::Storage::S3] the stored file
|
163
|
+
#
|
164
|
+
def store!(file)
|
165
|
+
connect!(uploader)
|
166
|
+
s3_options = {:access => uploader.s3_access, :content_type => file.content_type}
|
167
|
+
s3_options.merge!(uploader.s3_headers)
|
168
|
+
AWS::S3::S3Object.store(uploader.store_path, file.read, uploader.s3_bucket, s3_options)
|
169
|
+
CarrierWave::Storage::S3::File.new(uploader, uploader.store_path)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Do something to retrieve the file
|
173
|
+
#
|
174
|
+
# @param [CarrierWave::Uploader] uploader an uploader object
|
175
|
+
# @param [String] identifier uniquely identifies the file
|
176
|
+
#
|
177
|
+
# [identifier (String)] uniquely identifies the file
|
178
|
+
#
|
179
|
+
# === Returns
|
180
|
+
#
|
181
|
+
# [CarrierWave::Storage::S3::File] the stored file
|
182
|
+
#
|
183
|
+
def retrieve!(identifier)
|
184
|
+
connect!(uploader)
|
185
|
+
CarrierWave::Storage::S3::File.new(uploader, uploader.store_path(identifier))
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
def connect!(uploader)
|
191
|
+
AWS::S3::Base.establish_connection!(
|
192
|
+
:access_key_id => uploader.s3_access_key_id,
|
193
|
+
:secret_access_key => uploader.s3_secret_access_key
|
194
|
+
)
|
195
|
+
end
|
196
|
+
|
197
|
+
end # S3
|
198
|
+
end # Storage
|
199
|
+
end # CarrierWave
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Test
|
5
|
+
|
6
|
+
##
|
7
|
+
# These are some matchers that can be used in RSpec specs, to simplify the testing
|
8
|
+
# of uploaders.
|
9
|
+
#
|
10
|
+
module Matchers
|
11
|
+
|
12
|
+
class BeIdenticalTo # :nodoc:
|
13
|
+
def initialize(expected)
|
14
|
+
@expected = expected
|
15
|
+
end
|
16
|
+
def matches?(actual)
|
17
|
+
@actual = actual
|
18
|
+
FileUtils.identical?(@actual, @expected)
|
19
|
+
end
|
20
|
+
def failure_message
|
21
|
+
"expected #{@actual.inspect} to be identical to #{@expected.inspect}"
|
22
|
+
end
|
23
|
+
def negative_failure_message
|
24
|
+
"expected #{@actual.inspect} to not be identical to #{@expected.inspect}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def be_identical_to(expected)
|
29
|
+
BeIdenticalTo.new(expected)
|
30
|
+
end
|
31
|
+
|
32
|
+
class HavePermissions # :nodoc:
|
33
|
+
def initialize(expected)
|
34
|
+
@expected = expected
|
35
|
+
end
|
36
|
+
|
37
|
+
def matches?(actual)
|
38
|
+
@actual = actual
|
39
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
40
|
+
(File.stat(@actual.path).mode & 0777) == @expected
|
41
|
+
end
|
42
|
+
|
43
|
+
def failure_message
|
44
|
+
"expected #{@actual.inspect} to have permissions #{@expected.to_s(8)}, but they were #{(File.stat(@actual.path).mode & 0777).to_s(8)}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def negative_failure_message
|
48
|
+
"expected #{@actual.inspect} not to have permissions #{@expected.to_s(8)}, but it did"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def have_permissions(expected)
|
53
|
+
HavePermissions.new(expected)
|
54
|
+
end
|
55
|
+
|
56
|
+
class BeNoLargerThan # :nodoc:
|
57
|
+
def initialize(width, height)
|
58
|
+
@width, @height = width, height
|
59
|
+
end
|
60
|
+
|
61
|
+
def matches?(actual)
|
62
|
+
@actual = actual
|
63
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
64
|
+
img = ::Magick::Image.read(@actual.current_path).first
|
65
|
+
@actual_width = img.columns
|
66
|
+
@actual_height = img.rows
|
67
|
+
@actual_width <= @width && @actual_height <= @height
|
68
|
+
end
|
69
|
+
|
70
|
+
def failure_message
|
71
|
+
"expected #{@actual.current_path.inspect} to be no larger than #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
|
72
|
+
end
|
73
|
+
|
74
|
+
def negative_failure_message
|
75
|
+
"expected #{@actual.current_path.inspect} to be larger than #{@width} by #{@height}, but it wasn't."
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def be_no_larger_than(width, height)
|
80
|
+
load_rmagick
|
81
|
+
BeNoLargerThan.new(width, height)
|
82
|
+
end
|
83
|
+
|
84
|
+
class HaveDimensions # :nodoc:
|
85
|
+
def initialize(width, height)
|
86
|
+
@width, @height = width, height
|
87
|
+
end
|
88
|
+
|
89
|
+
def matches?(actual)
|
90
|
+
@actual = actual
|
91
|
+
# Satisfy expectation here. Return false or raise an error if it's not met.
|
92
|
+
img = ::Magick::Image.read(@actual.current_path).first
|
93
|
+
@actual_width = img.columns
|
94
|
+
@actual_height = img.rows
|
95
|
+
@actual_width == @width && @actual_height == @height
|
96
|
+
end
|
97
|
+
|
98
|
+
def failure_message
|
99
|
+
"expected #{@actual.current_path.inspect} to have an exact size of #{@width} by #{@height}, but it was #{@actual_width} by #{@actual_height}."
|
100
|
+
end
|
101
|
+
|
102
|
+
def negative_failure_message
|
103
|
+
"expected #{@actual.current_path.inspect} not to have an exact size of #{@width} by #{@height}, but it did."
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def have_dimensions(width, height)
|
108
|
+
load_rmagick
|
109
|
+
HaveDimensions.new(width, height)
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def load_rmagick
|
115
|
+
unless defined? Magick
|
116
|
+
begin
|
117
|
+
require 'rmagick'
|
118
|
+
rescue LoadError
|
119
|
+
require 'RMagick'
|
120
|
+
rescue LoadError
|
121
|
+
puts "WARNING: Failed to require rmagick, image processing may fail!"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end # SpecHelper
|
127
|
+
end # Test
|
128
|
+
end # CarrierWave
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
|
5
|
+
class FormNotMultipart < UploadError
|
6
|
+
def message
|
7
|
+
"You tried to assign a String or a Pathname to an uploader, for security reasons, this is not allowed.\n\n If this is a file upload, please check that your upload form is multipart encoded."
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
##
|
12
|
+
# Generates a unique cache id for use in the caching system
|
13
|
+
#
|
14
|
+
# === Returns
|
15
|
+
#
|
16
|
+
# [String] a cache id in the format YYYYMMDD-HHMM-PID-RND
|
17
|
+
#
|
18
|
+
def self.generate_cache_id
|
19
|
+
Time.now.strftime('%Y%m%d-%H%M') + '-' + Process.pid.to_s + '-' + ("%04d" % rand(9999))
|
20
|
+
end
|
21
|
+
|
22
|
+
module Uploader
|
23
|
+
module Cache
|
24
|
+
|
25
|
+
depends_on CarrierWave::Uploader::Callbacks
|
26
|
+
depends_on CarrierWave::Uploader::Configuration
|
27
|
+
|
28
|
+
module ClassMethods
|
29
|
+
|
30
|
+
##
|
31
|
+
# Removes cached files which are older than one day. You could call this method
|
32
|
+
# from a rake task to clean out old cached files.
|
33
|
+
#
|
34
|
+
# You can call this method directly on the module like this:
|
35
|
+
#
|
36
|
+
# CarrierWave.clean_cached_files!
|
37
|
+
#
|
38
|
+
# === Note
|
39
|
+
#
|
40
|
+
# This only works as long as you haven't done anything funky with your cache_dir.
|
41
|
+
# It's recommended that you keen cache files in one place only.
|
42
|
+
#
|
43
|
+
def clean_cached_files!
|
44
|
+
Dir.glob(File.expand_path(File.join(cache_dir, '*'), CarrierWave.root)).each do |dir|
|
45
|
+
time = dir.scan(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/).first.map { |t| t.to_i }
|
46
|
+
time = Time.utc(*time)
|
47
|
+
if time < (Time.now - (60*60*24))
|
48
|
+
FileUtils.rm_rf(dir)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Returns true if the uploader has been cached
|
56
|
+
#
|
57
|
+
# === Returns
|
58
|
+
#
|
59
|
+
# [Bool] whether the current file is cached
|
60
|
+
#
|
61
|
+
def cached?
|
62
|
+
@cache_id
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Returns a String which uniquely identifies the currently cached file for later retrieval
|
67
|
+
#
|
68
|
+
# === Returns
|
69
|
+
#
|
70
|
+
# [String] a cache name, in the format YYYYMMDD-HHMM-PID-RND/filename.txt
|
71
|
+
#
|
72
|
+
def cache_name
|
73
|
+
File.join(cache_id, full_original_filename) if cache_id and original_filename
|
74
|
+
end
|
75
|
+
|
76
|
+
##
|
77
|
+
# Caches the given file. Calls process! to trigger any process callbacks.
|
78
|
+
#
|
79
|
+
# === Parameters
|
80
|
+
#
|
81
|
+
# [new_file (File, IOString, Tempfile)] any kind of file object
|
82
|
+
#
|
83
|
+
# === Raises
|
84
|
+
#
|
85
|
+
# [CarrierWave::FormNotMultipart] if the assigned parameter is a string
|
86
|
+
#
|
87
|
+
def cache!(new_file)
|
88
|
+
new_file = CarrierWave::SanitizedFile.new(new_file)
|
89
|
+
raise CarrierWave::FormNotMultipart if new_file.is_path?
|
90
|
+
|
91
|
+
unless new_file.empty?
|
92
|
+
with_callbacks(:cache, new_file) do
|
93
|
+
self.cache_id = CarrierWave.generate_cache_id unless cache_id
|
94
|
+
|
95
|
+
@filename = new_file.filename
|
96
|
+
self.original_filename = new_file.filename
|
97
|
+
|
98
|
+
@file = new_file.copy_to(cache_path, permissions)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Retrieves the file with the given cache_name from the cache.
|
105
|
+
#
|
106
|
+
# === Parameters
|
107
|
+
#
|
108
|
+
# [cache_name (String)] uniquely identifies a cache file
|
109
|
+
#
|
110
|
+
# === Raises
|
111
|
+
#
|
112
|
+
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
|
113
|
+
#
|
114
|
+
def retrieve_from_cache!(cache_name)
|
115
|
+
with_callbacks(:retrieve_from_cache, cache_name) do
|
116
|
+
self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
|
117
|
+
@filename = original_filename
|
118
|
+
@file = CarrierWave::SanitizedFile.new(cache_path)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def cache_path
|
125
|
+
File.expand_path(File.join(cache_dir, cache_name), root)
|
126
|
+
end
|
127
|
+
|
128
|
+
attr_reader :cache_id, :original_filename
|
129
|
+
|
130
|
+
# We can override the full_original_filename method in other modules
|
131
|
+
alias_method :full_original_filename, :original_filename
|
132
|
+
|
133
|
+
def cache_id=(cache_id)
|
134
|
+
raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A[\d]{8}\-[\d]{4}\-[\d]+\-[\d]{4}\z/
|
135
|
+
@cache_id = cache_id
|
136
|
+
end
|
137
|
+
|
138
|
+
def original_filename=(filename)
|
139
|
+
raise CarrierWave::InvalidParameter, "invalid filename" unless filename =~ /\A[a-z0-9\.\-\+_]+\z/i
|
140
|
+
@original_filename = filename
|
141
|
+
end
|
142
|
+
|
143
|
+
end # Cache
|
144
|
+
end # Uploader
|
145
|
+
end # CarrierWave
|