carrierwave-rails3 0.4.5
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 +527 -0
- data/lib/carrierwave.rb +103 -0
- data/lib/carrierwave/compatibility/paperclip.rb +95 -0
- data/lib/carrierwave/core_ext/file.rb +11 -0
- data/lib/carrierwave/mount.rb +359 -0
- data/lib/carrierwave/orm/activerecord.rb +75 -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 +116 -0
- data/lib/carrierwave/processing/mini_magick.rb +261 -0
- data/lib/carrierwave/processing/rmagick.rb +278 -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 +104 -0
- data/lib/carrierwave/storage/right_s3.rb +3 -0
- data/lib/carrierwave/storage/s3.rb +206 -0
- data/lib/carrierwave/test/matchers.rb +164 -0
- data/lib/carrierwave/uploader.rb +44 -0
- data/lib/carrierwave/uploader/cache.rb +146 -0
- data/lib/carrierwave/uploader/callbacks.rb +41 -0
- data/lib/carrierwave/uploader/configuration.rb +134 -0
- data/lib/carrierwave/uploader/default_url.rb +19 -0
- data/lib/carrierwave/uploader/download.rb +60 -0
- data/lib/carrierwave/uploader/extension_whitelist.rb +38 -0
- data/lib/carrierwave/uploader/mountable.rb +39 -0
- data/lib/carrierwave/uploader/processing.rb +84 -0
- data/lib/carrierwave/uploader/proxy.rb +62 -0
- data/lib/carrierwave/uploader/remove.rb +23 -0
- data/lib/carrierwave/uploader/store.rb +90 -0
- data/lib/carrierwave/uploader/url.rb +33 -0
- data/lib/carrierwave/uploader/versions.rb +147 -0
- data/lib/generators/templates/uploader.rb +47 -0
- data/lib/generators/uploader_generator.rb +13 -0
- data/spec/compatibility/paperclip_spec.rb +52 -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/cloudfiles_spec.rb +78 -0
- data/spec/storage/grid_fs_spec.rb +86 -0
- data/spec/storage/s3_spec.rb +118 -0
- data/spec/uploader/cache_spec.rb +209 -0
- data/spec/uploader/callback_spec.rb +24 -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 +128 -0
@@ -0,0 +1,164 @@
|
|
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
|
+
image = ImageLoader.load_image(@actual.current_path)
|
65
|
+
@actual_width = image.width
|
66
|
+
@actual_height = image.height
|
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
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def be_no_larger_than(width, height)
|
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
|
+
image = ImageLoader.load_image(@actual.current_path)
|
93
|
+
@actual_width = image.width
|
94
|
+
@actual_height = image.height
|
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
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
def have_dimensions(width, height)
|
109
|
+
HaveDimensions.new(width, height)
|
110
|
+
end
|
111
|
+
|
112
|
+
class ImageLoader # :nodoc:
|
113
|
+
def self.load_image(filename)
|
114
|
+
if defined? MiniMagick
|
115
|
+
MiniMagickWrapper.new(filename)
|
116
|
+
else
|
117
|
+
unless defined? Magick
|
118
|
+
begin
|
119
|
+
require 'rmagick'
|
120
|
+
rescue LoadError
|
121
|
+
require 'RMagick'
|
122
|
+
rescue LoadError
|
123
|
+
puts "WARNING: Failed to require rmagick, image processing may fail!"
|
124
|
+
end
|
125
|
+
end
|
126
|
+
MagickWrapper.new(filename)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
class MagickWrapper # :nodoc:
|
132
|
+
attr_reader :image
|
133
|
+
def width
|
134
|
+
image.columns
|
135
|
+
end
|
136
|
+
|
137
|
+
def height
|
138
|
+
image.rows
|
139
|
+
end
|
140
|
+
|
141
|
+
def initialize(filename)
|
142
|
+
@image = ::Magick::Image.read(filename).first
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class MiniMagickWrapper # :nodoc:
|
147
|
+
attr_reader :image
|
148
|
+
def width
|
149
|
+
image[:width]
|
150
|
+
end
|
151
|
+
|
152
|
+
def height
|
153
|
+
image[:height]
|
154
|
+
end
|
155
|
+
|
156
|
+
def initialize(filename)
|
157
|
+
@image = ::MiniMagick::Image.from_file(filename)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
end # Matchers
|
162
|
+
end # Test
|
163
|
+
end # CarrierWave
|
164
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
|
5
|
+
##
|
6
|
+
# See CarrierWave::Uploader::Base
|
7
|
+
#
|
8
|
+
module Uploader
|
9
|
+
|
10
|
+
##
|
11
|
+
# An uploader is a class that allows you to easily handle the caching and storage of
|
12
|
+
# uploaded files. Please refer to the README for configuration options.
|
13
|
+
#
|
14
|
+
# Once you have an uploader you can use it in isolation:
|
15
|
+
#
|
16
|
+
# my_uploader = MyUploader.new
|
17
|
+
# my_uploader.cache!(File.open(path_to_file))
|
18
|
+
# my_uploader.retrieve_from_store!('monkey.png')
|
19
|
+
#
|
20
|
+
# Alternatively, you can mount it on an ORM or other persistence layer, with
|
21
|
+
# +CarrierWave::Mount#mount_uploader+. There are extensions for activerecord and datamapper
|
22
|
+
# these are *very* simple (they are only a dozen lines of code), so adding your own should
|
23
|
+
# be trivial.
|
24
|
+
#
|
25
|
+
class Base
|
26
|
+
attr_reader :file
|
27
|
+
|
28
|
+
include CarrierWave::Uploader::Callbacks
|
29
|
+
include CarrierWave::Uploader::Proxy
|
30
|
+
include CarrierWave::Uploader::Url
|
31
|
+
include CarrierWave::Uploader::Mountable
|
32
|
+
include CarrierWave::Uploader::Cache
|
33
|
+
include CarrierWave::Uploader::Store
|
34
|
+
include CarrierWave::Uploader::Download
|
35
|
+
include CarrierWave::Uploader::Remove
|
36
|
+
include CarrierWave::Uploader::ExtensionWhitelist
|
37
|
+
include CarrierWave::Uploader::Processing
|
38
|
+
include CarrierWave::Uploader::Versions
|
39
|
+
include CarrierWave::Uploader::DefaultUrl
|
40
|
+
include CarrierWave::Uploader::Configuration
|
41
|
+
end # Base
|
42
|
+
|
43
|
+
end # Uploader
|
44
|
+
end # CarrierWave
|
@@ -0,0 +1,146 @@
|
|
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
|
+
extend ActiveSupport::Concern
|
25
|
+
|
26
|
+
include CarrierWave::Uploader::Callbacks
|
27
|
+
include CarrierWave::Uploader::Configuration
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
|
31
|
+
##
|
32
|
+
# Removes cached files which are older than one day. You could call this method
|
33
|
+
# from a rake task to clean out old cached files.
|
34
|
+
#
|
35
|
+
# You can call this method directly on the module like this:
|
36
|
+
#
|
37
|
+
# CarrierWave.clean_cached_files!
|
38
|
+
#
|
39
|
+
# === Note
|
40
|
+
#
|
41
|
+
# This only works as long as you haven't done anything funky with your cache_dir.
|
42
|
+
# It's recommended that you keep cache files in one place only.
|
43
|
+
#
|
44
|
+
def clean_cached_files!
|
45
|
+
Dir.glob(File.expand_path(File.join(cache_dir, '*'), CarrierWave.root)).each do |dir|
|
46
|
+
time = dir.scan(/(\d{4})(\d{2})(\d{2})-(\d{2})(\d{2})/).first.map { |t| t.to_i }
|
47
|
+
time = Time.utc(*time)
|
48
|
+
if time < (Time.now - (60*60*24))
|
49
|
+
FileUtils.rm_rf(dir)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Returns true if the uploader has been cached
|
57
|
+
#
|
58
|
+
# === Returns
|
59
|
+
#
|
60
|
+
# [Bool] whether the current file is cached
|
61
|
+
#
|
62
|
+
def cached?
|
63
|
+
@cache_id
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Returns a String which uniquely identifies the currently cached file for later retrieval
|
68
|
+
#
|
69
|
+
# === Returns
|
70
|
+
#
|
71
|
+
# [String] a cache name, in the format YYYYMMDD-HHMM-PID-RND/filename.txt
|
72
|
+
#
|
73
|
+
def cache_name
|
74
|
+
File.join(cache_id, full_original_filename) if cache_id and original_filename
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Caches the given file. Calls process! to trigger any process callbacks.
|
79
|
+
#
|
80
|
+
# === Parameters
|
81
|
+
#
|
82
|
+
# [new_file (File, IOString, Tempfile)] any kind of file object
|
83
|
+
#
|
84
|
+
# === Raises
|
85
|
+
#
|
86
|
+
# [CarrierWave::FormNotMultipart] if the assigned parameter is a string
|
87
|
+
#
|
88
|
+
def cache!(new_file)
|
89
|
+
new_file = CarrierWave::SanitizedFile.new(new_file)
|
90
|
+
raise CarrierWave::FormNotMultipart if new_file.is_path?
|
91
|
+
|
92
|
+
unless new_file.empty?
|
93
|
+
with_callbacks(:cache, new_file) do
|
94
|
+
self.cache_id = CarrierWave.generate_cache_id unless cache_id
|
95
|
+
|
96
|
+
@filename = new_file.filename
|
97
|
+
self.original_filename = new_file.filename
|
98
|
+
|
99
|
+
@file = new_file.copy_to(cache_path, permissions)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Retrieves the file with the given cache_name from the cache.
|
106
|
+
#
|
107
|
+
# === Parameters
|
108
|
+
#
|
109
|
+
# [cache_name (String)] uniquely identifies a cache file
|
110
|
+
#
|
111
|
+
# === Raises
|
112
|
+
#
|
113
|
+
# [CarrierWave::InvalidParameter] if the cache_name is incorrectly formatted.
|
114
|
+
#
|
115
|
+
def retrieve_from_cache!(cache_name)
|
116
|
+
with_callbacks(:retrieve_from_cache, cache_name) do
|
117
|
+
self.cache_id, self.original_filename = cache_name.to_s.split('/', 2)
|
118
|
+
@filename = original_filename
|
119
|
+
@file = CarrierWave::SanitizedFile.new(cache_path)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def cache_path
|
126
|
+
File.expand_path(File.join(cache_dir, cache_name), root)
|
127
|
+
end
|
128
|
+
|
129
|
+
attr_reader :cache_id, :original_filename
|
130
|
+
|
131
|
+
# We can override the full_original_filename method in other modules
|
132
|
+
alias_method :full_original_filename, :original_filename
|
133
|
+
|
134
|
+
def cache_id=(cache_id)
|
135
|
+
raise CarrierWave::InvalidParameter, "invalid cache id" unless cache_id =~ /\A[\d]{8}\-[\d]{4}\-[\d]+\-[\d]{4}\z/
|
136
|
+
@cache_id = cache_id
|
137
|
+
end
|
138
|
+
|
139
|
+
def original_filename=(filename)
|
140
|
+
raise CarrierWave::InvalidParameter, "invalid filename" unless filename =~ /\A[a-z0-9\.\-\+_]+\z/i
|
141
|
+
@original_filename = filename
|
142
|
+
end
|
143
|
+
|
144
|
+
end # Cache
|
145
|
+
end # Uploader
|
146
|
+
end # CarrierWave
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module Callbacks
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
class_inheritable_accessor :_before_callbacks, :_after_callbacks
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_callbacks(kind, *args)
|
13
|
+
self.class._before_callbacks_for(kind).each { |callback| self.send(callback, *args) }
|
14
|
+
yield
|
15
|
+
self.class._after_callbacks_for(kind).each { |callback| self.send(callback, *args) }
|
16
|
+
end
|
17
|
+
|
18
|
+
module ClassMethods
|
19
|
+
|
20
|
+
def _before_callbacks_for(kind) #:nodoc:
|
21
|
+
(self._before_callbacks || { kind => [] })[kind] || []
|
22
|
+
end
|
23
|
+
|
24
|
+
def _after_callbacks_for(kind) #:nodoc:
|
25
|
+
(self._after_callbacks || { kind => [] })[kind] || []
|
26
|
+
end
|
27
|
+
|
28
|
+
def before(kind, callback)
|
29
|
+
self._before_callbacks ||= {}
|
30
|
+
self._before_callbacks[kind] = _before_callbacks_for(kind) + [callback]
|
31
|
+
end
|
32
|
+
|
33
|
+
def after(kind, callback)
|
34
|
+
self._after_callbacks ||= {}
|
35
|
+
self._after_callbacks[kind] = _after_callbacks_for(kind) + [callback]
|
36
|
+
end
|
37
|
+
end # ClassMethods
|
38
|
+
|
39
|
+
end # Callbacks
|
40
|
+
end # Uploader
|
41
|
+
end # CarrierWave
|
@@ -0,0 +1,134 @@
|
|
1
|
+
module CarrierWave
|
2
|
+
|
3
|
+
module Uploader
|
4
|
+
module Configuration
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
add_config :root
|
9
|
+
add_config :permissions
|
10
|
+
add_config :storage_engines
|
11
|
+
add_config :s3_access # for old aws/s3
|
12
|
+
add_config :s3_access_policy # for aws
|
13
|
+
add_config :s3_bucket
|
14
|
+
add_config :s3_access_key_id
|
15
|
+
add_config :s3_secret_access_key
|
16
|
+
add_config :s3_cnamed
|
17
|
+
add_config :s3_headers
|
18
|
+
add_config :s3_multi_thread
|
19
|
+
add_config :cloud_files_username
|
20
|
+
add_config :cloud_files_api_key
|
21
|
+
add_config :cloud_files_container
|
22
|
+
add_config :grid_fs_database
|
23
|
+
add_config :grid_fs_host
|
24
|
+
add_config :grid_fs_port
|
25
|
+
add_config :grid_fs_username
|
26
|
+
add_config :grid_fs_password
|
27
|
+
add_config :grid_fs_access_url
|
28
|
+
add_config :store_dir
|
29
|
+
add_config :cache_dir
|
30
|
+
add_config :enable_processing
|
31
|
+
|
32
|
+
# Mounting
|
33
|
+
add_config :ignore_integrity_errors
|
34
|
+
add_config :ignore_processing_errors
|
35
|
+
add_config :validate_integrity
|
36
|
+
add_config :validate_processing
|
37
|
+
add_config :mount_on
|
38
|
+
|
39
|
+
configure do |config|
|
40
|
+
config.permissions = 0644
|
41
|
+
config.storage_engines = {
|
42
|
+
:file => "CarrierWave::Storage::File",
|
43
|
+
:s3 => "CarrierWave::Storage::S3",
|
44
|
+
:grid_fs => "CarrierWave::Storage::GridFS",
|
45
|
+
:right_s3 => "CarrierWave::Storage::RightS3",
|
46
|
+
:cloud_files => "CarrierWave::Storage::CloudFiles"
|
47
|
+
}
|
48
|
+
config.storage = :file
|
49
|
+
#config.s3_access = :public_read
|
50
|
+
#config.s3_access_policy = 'public-read' # Now set in library
|
51
|
+
config.s3_headers = {}
|
52
|
+
config.s3_multi_thread = true
|
53
|
+
config.grid_fs_database = 'carrierwave'
|
54
|
+
config.grid_fs_host = 'localhost'
|
55
|
+
config.grid_fs_port = 27017
|
56
|
+
config.store_dir = 'uploads'
|
57
|
+
config.cache_dir = 'uploads/tmp'
|
58
|
+
config.ignore_integrity_errors = true
|
59
|
+
config.ignore_processing_errors = true
|
60
|
+
config.validate_integrity = true
|
61
|
+
config.validate_processing = true
|
62
|
+
config.root = CarrierWave.root
|
63
|
+
config.enable_processing = true
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
module ClassMethods
|
68
|
+
|
69
|
+
##
|
70
|
+
# Sets the storage engine to be used when storing files with this uploader.
|
71
|
+
# Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
|
72
|
+
# method. See lib/carrierwave/storage/file.rb for an example. Storage engines should
|
73
|
+
# be added to CarrierWave::Uploader::Base.storage_engines so they can be referred
|
74
|
+
# to by a symbol, which should be more convenient
|
75
|
+
#
|
76
|
+
# If no argument is given, it will simply return the currently used storage engine.
|
77
|
+
#
|
78
|
+
# === Parameters
|
79
|
+
#
|
80
|
+
# [storage (Symbol, Class)] The storage engine to use for this uploader
|
81
|
+
#
|
82
|
+
# === Returns
|
83
|
+
#
|
84
|
+
# [Class] the storage engine to be used with this uploader
|
85
|
+
#
|
86
|
+
# === Examples
|
87
|
+
#
|
88
|
+
# storage :file
|
89
|
+
# storage CarrierWave::Storage::File
|
90
|
+
# storage MyCustomStorageEngine
|
91
|
+
#
|
92
|
+
def storage(storage = nil)
|
93
|
+
if storage.is_a?(Symbol)
|
94
|
+
@storage = eval(storage_engines[storage])
|
95
|
+
elsif storage
|
96
|
+
@storage = storage
|
97
|
+
elsif @storage.nil?
|
98
|
+
# Get the storage from the superclass if there is one
|
99
|
+
@storage = superclass.storage rescue nil
|
100
|
+
end
|
101
|
+
return @storage
|
102
|
+
end
|
103
|
+
alias_method :storage=, :storage
|
104
|
+
|
105
|
+
|
106
|
+
def add_config(name)
|
107
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
108
|
+
def self.#{name}(value=nil)
|
109
|
+
@#{name} = value if value
|
110
|
+
return @#{name} if self.object_id == #{self.object_id} || defined?(@#{name})
|
111
|
+
name = superclass.#{name}
|
112
|
+
return nil if name.nil? && !instance_variable_defined?("@#{name}")
|
113
|
+
@#{name} = name && !name.is_a?(Module) && !name.is_a?(Symbol) && !name.is_a?(Numeric) && !name.is_a?(TrueClass) && !name.is_a?(FalseClass) ? name.dup : name
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.#{name}=(value)
|
117
|
+
@#{name} = value
|
118
|
+
end
|
119
|
+
|
120
|
+
def #{name}
|
121
|
+
self.class.#{name}
|
122
|
+
end
|
123
|
+
RUBY
|
124
|
+
end
|
125
|
+
|
126
|
+
def configure
|
127
|
+
yield self
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|