carrierwave-pressplane 0.5.8.3
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.md +748 -0
- data/lib/carrierwave.rb +116 -0
- data/lib/carrierwave/compatibility/paperclip.rb +95 -0
- data/lib/carrierwave/locale/en.yml +9 -0
- data/lib/carrierwave/mount.rb +382 -0
- data/lib/carrierwave/orm/activerecord.rb +46 -0
- data/lib/carrierwave/processing/mime_types.rb +58 -0
- data/lib/carrierwave/processing/mini_magick.rb +252 -0
- data/lib/carrierwave/processing/rmagick.rb +279 -0
- data/lib/carrierwave/sanitized_file.rb +315 -0
- data/lib/carrierwave/storage/abstract.rb +30 -0
- data/lib/carrierwave/storage/cloud_files.rb +188 -0
- data/lib/carrierwave/storage/file.rb +56 -0
- data/lib/carrierwave/storage/fog.rb +333 -0
- data/lib/carrierwave/storage/right_s3.rb +1 -0
- data/lib/carrierwave/storage/s3.rb +240 -0
- data/lib/carrierwave/test/matchers.rb +241 -0
- data/lib/carrierwave/uploader.rb +44 -0
- data/lib/carrierwave/uploader/cache.rb +178 -0
- data/lib/carrierwave/uploader/callbacks.rb +35 -0
- data/lib/carrierwave/uploader/configuration.rb +168 -0
- data/lib/carrierwave/uploader/default_url.rb +19 -0
- data/lib/carrierwave/uploader/download.rb +75 -0
- data/lib/carrierwave/uploader/extension_whitelist.rb +49 -0
- data/lib/carrierwave/uploader/mountable.rb +39 -0
- data/lib/carrierwave/uploader/processing.rb +90 -0
- data/lib/carrierwave/uploader/proxy.rb +77 -0
- data/lib/carrierwave/uploader/remove.rb +23 -0
- data/lib/carrierwave/uploader/store.rb +113 -0
- data/lib/carrierwave/uploader/url.rb +47 -0
- data/lib/carrierwave/uploader/versions.rb +237 -0
- data/lib/carrierwave/validations/active_model.rb +64 -0
- data/lib/carrierwave/version.rb +3 -0
- data/lib/generators/templates/uploader.rb +48 -0
- data/lib/generators/uploader_generator.rb +7 -0
- metadata +215 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module CarrierWave
|
|
4
|
+
module Uploader
|
|
5
|
+
module Proxy
|
|
6
|
+
|
|
7
|
+
##
|
|
8
|
+
# === Returns
|
|
9
|
+
#
|
|
10
|
+
# [Boolean] Whether the uploaded file is blank
|
|
11
|
+
#
|
|
12
|
+
def blank?
|
|
13
|
+
file.blank?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
##
|
|
17
|
+
# === Returns
|
|
18
|
+
#
|
|
19
|
+
# [String] the path where the file is currently located.
|
|
20
|
+
#
|
|
21
|
+
def current_path
|
|
22
|
+
file.path if file.respond_to?(:path)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
alias_method :path, :current_path
|
|
26
|
+
|
|
27
|
+
##
|
|
28
|
+
# Returns a string that uniquely identifies the last stored file
|
|
29
|
+
#
|
|
30
|
+
# === Returns
|
|
31
|
+
#
|
|
32
|
+
# [String] uniquely identifies a file
|
|
33
|
+
#
|
|
34
|
+
def identifier
|
|
35
|
+
storage.identifier if storage.respond_to?(:identifier)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# Read the contents of the file
|
|
40
|
+
#
|
|
41
|
+
# === Returns
|
|
42
|
+
#
|
|
43
|
+
# [String] contents of the file
|
|
44
|
+
#
|
|
45
|
+
def read
|
|
46
|
+
file.read if file.respond_to?(:read)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
# Fetches the size of the currently stored/cached file
|
|
51
|
+
#
|
|
52
|
+
# === Returns
|
|
53
|
+
#
|
|
54
|
+
# [Integer] size of the file
|
|
55
|
+
#
|
|
56
|
+
def size
|
|
57
|
+
file.respond_to?(:size) ? file.size : 0
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
# Return the size of the file when asked for its length
|
|
62
|
+
#
|
|
63
|
+
# === Returns
|
|
64
|
+
#
|
|
65
|
+
# [Integer] size of the file
|
|
66
|
+
#
|
|
67
|
+
# === Note
|
|
68
|
+
#
|
|
69
|
+
# This was added because of the way Rails handles length/size validations in 3.0.6 and above.
|
|
70
|
+
#
|
|
71
|
+
def length
|
|
72
|
+
size
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end # Proxy
|
|
76
|
+
end # Uploader
|
|
77
|
+
end # CarrierWave
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module CarrierWave
|
|
4
|
+
module Uploader
|
|
5
|
+
module Remove
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
include CarrierWave::Uploader::Callbacks
|
|
9
|
+
|
|
10
|
+
##
|
|
11
|
+
# Removes the file and reset it
|
|
12
|
+
#
|
|
13
|
+
def remove!
|
|
14
|
+
with_callbacks(:remove) do
|
|
15
|
+
@file.delete if @file
|
|
16
|
+
@file = nil
|
|
17
|
+
@cache_id = nil
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end # Remove
|
|
22
|
+
end # Uploader
|
|
23
|
+
end # CarrierWave
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module CarrierWave
|
|
4
|
+
module Uploader
|
|
5
|
+
module Store
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
include CarrierWave::Uploader::Callbacks
|
|
9
|
+
include CarrierWave::Uploader::Configuration
|
|
10
|
+
include CarrierWave::Uploader::Cache
|
|
11
|
+
|
|
12
|
+
##
|
|
13
|
+
# Override this in your Uploader to change the filename.
|
|
14
|
+
#
|
|
15
|
+
# Be careful using record ids as filenames. If the filename is stored in the database
|
|
16
|
+
# the record id will be nil when the filename is set. Don't use record ids unless you
|
|
17
|
+
# understand this limitation.
|
|
18
|
+
#
|
|
19
|
+
# Do not use the version_name in the filename, as it will prevent versions from being
|
|
20
|
+
# loaded correctly.
|
|
21
|
+
#
|
|
22
|
+
# === Returns
|
|
23
|
+
#
|
|
24
|
+
# [String] a filename
|
|
25
|
+
#
|
|
26
|
+
def filename
|
|
27
|
+
@filename
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
##
|
|
31
|
+
# Calculates the path where the file should be stored. If +for_file+ is given, it will be
|
|
32
|
+
# used as the filename, otherwise +CarrierWave::Uploader#filename+ is assumed.
|
|
33
|
+
#
|
|
34
|
+
# === Parameters
|
|
35
|
+
#
|
|
36
|
+
# [for_file (String)] name of the file <optional>
|
|
37
|
+
#
|
|
38
|
+
# === Returns
|
|
39
|
+
#
|
|
40
|
+
# [String] the store path
|
|
41
|
+
#
|
|
42
|
+
def store_path(for_file=filename)
|
|
43
|
+
File.join([store_dir, full_filename(for_file)].compact)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
##
|
|
47
|
+
# Stores the file by passing it to this Uploader's storage engine.
|
|
48
|
+
#
|
|
49
|
+
# If new_file is omitted, a previously cached file will be stored.
|
|
50
|
+
#
|
|
51
|
+
# === Parameters
|
|
52
|
+
#
|
|
53
|
+
# [new_file (File, IOString, Tempfile)] any kind of file object
|
|
54
|
+
#
|
|
55
|
+
def store!(new_file=nil)
|
|
56
|
+
cache!(new_file) if new_file && ((@cache_id != parent_cache_id) || @cache_id.nil?)
|
|
57
|
+
if @file and @cache_id
|
|
58
|
+
with_callbacks(:store, new_file) do
|
|
59
|
+
new_file = storage.store!(@file)
|
|
60
|
+
@file.delete if (delete_tmp_file_after_storage && ! move_to_store)
|
|
61
|
+
delete_cache_id
|
|
62
|
+
@file = new_file
|
|
63
|
+
@cache_id = nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
##
|
|
69
|
+
# Deletes a cache id (tmp dir in cache)
|
|
70
|
+
#
|
|
71
|
+
def delete_cache_id
|
|
72
|
+
if @cache_id
|
|
73
|
+
path = File.expand_path(File.join(cache_dir, @cache_id), CarrierWave.root)
|
|
74
|
+
begin
|
|
75
|
+
Dir.rmdir(path)
|
|
76
|
+
rescue Errno::ENOENT
|
|
77
|
+
# Ignore: path does not exist
|
|
78
|
+
rescue Errno::ENOTDIR
|
|
79
|
+
# Ignore: path is not a dir
|
|
80
|
+
rescue Errno::ENOTEMPTY, Errno::EEXIST
|
|
81
|
+
# Ignore: dir is not empty
|
|
82
|
+
rescue SystemCallError
|
|
83
|
+
# no such directory on JRuby
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# Retrieves the file from the storage.
|
|
90
|
+
#
|
|
91
|
+
# === Parameters
|
|
92
|
+
#
|
|
93
|
+
# [identifier (String)] uniquely identifies the file to retrieve
|
|
94
|
+
#
|
|
95
|
+
def retrieve_from_store!(identifier)
|
|
96
|
+
with_callbacks(:retrieve_from_store, identifier) do
|
|
97
|
+
@file = storage.retrieve!(identifier)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
private
|
|
102
|
+
|
|
103
|
+
def full_filename(for_file)
|
|
104
|
+
for_file
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def storage
|
|
108
|
+
@storage ||= self.class.storage.new(self)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end # Store
|
|
112
|
+
end # Uploader
|
|
113
|
+
end # CarrierWave
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
module CarrierWave
|
|
4
|
+
module Uploader
|
|
5
|
+
module Url
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
include CarrierWave::Uploader::Configuration
|
|
8
|
+
|
|
9
|
+
##
|
|
10
|
+
# === Returns
|
|
11
|
+
#
|
|
12
|
+
# [String] the location where this file is accessible via a url
|
|
13
|
+
#
|
|
14
|
+
def url
|
|
15
|
+
if file.respond_to?(:url) and not file.url.blank?
|
|
16
|
+
file.url
|
|
17
|
+
elsif current_path
|
|
18
|
+
(base_path || "") + File.expand_path(current_path).gsub(File.expand_path(root), '')
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
alias_method :to_s, :url
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# === Returns
|
|
26
|
+
#
|
|
27
|
+
# [Hash] the locations where this file and versions are accessible via a url
|
|
28
|
+
#
|
|
29
|
+
def as_json(options = nil)
|
|
30
|
+
h = { :url => url }
|
|
31
|
+
h.merge Hash[versions.map { |name, version| [name, { :url => version.url }] }]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
##
|
|
35
|
+
# FIXME to_xml should work like to_json, but this is the best we've been able to do so far.
|
|
36
|
+
# This hack fixes issue #337.
|
|
37
|
+
#
|
|
38
|
+
# === Returns
|
|
39
|
+
#
|
|
40
|
+
# [nil]
|
|
41
|
+
#
|
|
42
|
+
def to_xml(options = nil)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
end # Url
|
|
46
|
+
end # Uploader
|
|
47
|
+
end # CarrierWave
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require 'active_support/deprecation'
|
|
4
|
+
|
|
5
|
+
module CarrierWave
|
|
6
|
+
module Uploader
|
|
7
|
+
module Versions
|
|
8
|
+
extend ActiveSupport::Concern
|
|
9
|
+
|
|
10
|
+
include CarrierWave::Uploader::Callbacks
|
|
11
|
+
|
|
12
|
+
included do
|
|
13
|
+
##
|
|
14
|
+
# Add configuration options for versions
|
|
15
|
+
# class_inheritable_accessor was deprecated in Rails 3.1 and removed for 3.2.
|
|
16
|
+
# class_attribute was added in 3.0, but doesn't support omitting the instance_reader until 3.0.10
|
|
17
|
+
# For max compatibility, always use class_inheritable_accessor when possible
|
|
18
|
+
if respond_to?(:class_inheritable_accessor)
|
|
19
|
+
ActiveSupport::Deprecation.silence do
|
|
20
|
+
class_inheritable_accessor :versions, :version_names, :instance_reader => false, :instance_writer => false
|
|
21
|
+
end
|
|
22
|
+
else
|
|
23
|
+
class_attribute :versions, :version_names, :instance_reader => false, :instance_writer => false
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
self.versions = {}
|
|
27
|
+
self.version_names = []
|
|
28
|
+
|
|
29
|
+
attr_accessor :parent_cache_id
|
|
30
|
+
|
|
31
|
+
after :cache, :assign_parent_cache_id
|
|
32
|
+
after :cache, :cache_versions!
|
|
33
|
+
after :store, :store_versions!
|
|
34
|
+
after :remove, :remove_versions!
|
|
35
|
+
after :retrieve_from_cache, :retrieve_versions_from_cache!
|
|
36
|
+
after :retrieve_from_store, :retrieve_versions_from_store!
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
module ClassMethods
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# Adds a new version to this uploader
|
|
43
|
+
#
|
|
44
|
+
# === Parameters
|
|
45
|
+
#
|
|
46
|
+
# [name (#to_sym)] name of the version
|
|
47
|
+
# [options (Hash)] optional options hash
|
|
48
|
+
# [&block (Proc)] a block to eval on this version of the uploader
|
|
49
|
+
#
|
|
50
|
+
# === Examples
|
|
51
|
+
#
|
|
52
|
+
# class MyUploader < CarrierWave::Uploader::Base
|
|
53
|
+
#
|
|
54
|
+
# version :thumb do
|
|
55
|
+
# process :scale => [200, 200]
|
|
56
|
+
# end
|
|
57
|
+
#
|
|
58
|
+
# version :preview, :if => :image? do
|
|
59
|
+
# process :scale => [200, 200]
|
|
60
|
+
# end
|
|
61
|
+
#
|
|
62
|
+
# end
|
|
63
|
+
#
|
|
64
|
+
def version(name, options = {}, &block)
|
|
65
|
+
name = name.to_sym
|
|
66
|
+
unless versions[name]
|
|
67
|
+
uploader = Class.new(self)
|
|
68
|
+
uploader.versions = {}
|
|
69
|
+
|
|
70
|
+
# Define the enable_processing method for versions so they get the
|
|
71
|
+
# value from the parent class unless explicitly overwritten
|
|
72
|
+
uploader.class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
73
|
+
def self.enable_processing(value=nil)
|
|
74
|
+
self.enable_processing = value if value
|
|
75
|
+
if !@enable_processing.nil?
|
|
76
|
+
@enable_processing
|
|
77
|
+
else
|
|
78
|
+
superclass.enable_processing
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
RUBY
|
|
82
|
+
|
|
83
|
+
# Add the current version hash to class attribute :versions
|
|
84
|
+
current_version = {}
|
|
85
|
+
current_version[name] = {
|
|
86
|
+
:uploader => uploader,
|
|
87
|
+
:options => options
|
|
88
|
+
}
|
|
89
|
+
self.versions = versions.merge(current_version)
|
|
90
|
+
|
|
91
|
+
versions[name][:uploader].version_names += [name]
|
|
92
|
+
|
|
93
|
+
class_eval <<-RUBY
|
|
94
|
+
def #{name}
|
|
95
|
+
versions[:#{name}]
|
|
96
|
+
end
|
|
97
|
+
RUBY
|
|
98
|
+
# as the processors get the output from the previous processors as their
|
|
99
|
+
# input we must not stack the processors here
|
|
100
|
+
versions[name][:uploader].processors = versions[name][:uploader].processors.dup
|
|
101
|
+
versions[name][:uploader].processors.clear
|
|
102
|
+
end
|
|
103
|
+
versions[name][:uploader].class_eval(&block) if block
|
|
104
|
+
versions[name]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def recursively_apply_block_to_versions(&block)
|
|
108
|
+
versions.each do |name, version|
|
|
109
|
+
version[:uploader].class_eval(&block)
|
|
110
|
+
version[:uploader].recursively_apply_block_to_versions(&block)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end # ClassMethods
|
|
114
|
+
|
|
115
|
+
##
|
|
116
|
+
# Returns a hash mapping the name of each version of the uploader to an instance of it
|
|
117
|
+
#
|
|
118
|
+
# === Returns
|
|
119
|
+
#
|
|
120
|
+
# [Hash{Symbol => CarrierWave::Uploader}] a list of uploader instances
|
|
121
|
+
#
|
|
122
|
+
def versions
|
|
123
|
+
return @versions if @versions
|
|
124
|
+
@versions = {}
|
|
125
|
+
self.class.versions.each do |name, version|
|
|
126
|
+
@versions[name] = version[:uploader].new(model, mounted_as)
|
|
127
|
+
end
|
|
128
|
+
@versions
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
# === Returns
|
|
133
|
+
#
|
|
134
|
+
# [String] the name of this version of the uploader
|
|
135
|
+
#
|
|
136
|
+
def version_name
|
|
137
|
+
self.class.version_names.join('_').to_sym unless self.class.version_names.blank?
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
##
|
|
141
|
+
# When given a version name as a parameter, will return the url for that version
|
|
142
|
+
# This also works with nested versions.
|
|
143
|
+
#
|
|
144
|
+
# === Example
|
|
145
|
+
#
|
|
146
|
+
# my_uploader.url # => /path/to/my/uploader.gif
|
|
147
|
+
# my_uploader.url(:thumb) # => /path/to/my/thumb_uploader.gif
|
|
148
|
+
# my_uploader.url(:thumb, :small) # => /path/to/my/thumb_small_uploader.gif
|
|
149
|
+
#
|
|
150
|
+
# === Parameters
|
|
151
|
+
#
|
|
152
|
+
# [*args (Symbol)] any number of versions
|
|
153
|
+
#
|
|
154
|
+
# === Returns
|
|
155
|
+
#
|
|
156
|
+
# [String] the location where this file is accessible via a url
|
|
157
|
+
#
|
|
158
|
+
def url(*args)
|
|
159
|
+
if(args.first)
|
|
160
|
+
raise ArgumentError, "Version #{args.first} doesn't exist!" if versions[args.first.to_sym].nil?
|
|
161
|
+
# recursively proxy to version
|
|
162
|
+
versions[args.first.to_sym].url(*args[1..-1])
|
|
163
|
+
else
|
|
164
|
+
super()
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
##
|
|
169
|
+
# Recreate versions and reprocess them. This can be used to recreate
|
|
170
|
+
# versions if their parameters somehow have changed.
|
|
171
|
+
#
|
|
172
|
+
def recreate_versions!
|
|
173
|
+
# Some files could possibly not be stored on the local disk. This
|
|
174
|
+
# doesn't play nicely with processing. Make sure that we're only
|
|
175
|
+
# processing a cached file
|
|
176
|
+
#
|
|
177
|
+
# The call to store! will trigger the necessary callbacks to both
|
|
178
|
+
# process this version and all sub-versions
|
|
179
|
+
cache_stored_file! if !cached?
|
|
180
|
+
|
|
181
|
+
store!
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
private
|
|
185
|
+
def assign_parent_cache_id(file)
|
|
186
|
+
active_versions.each do |name, uploader|
|
|
187
|
+
uploader.parent_cache_id = @cache_id
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def active_versions
|
|
192
|
+
versions.select do |name, uploader|
|
|
193
|
+
condition = self.class.versions[name][:options][:if]
|
|
194
|
+
not condition or send(condition, file)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def full_filename(for_file)
|
|
199
|
+
[version_name, super(for_file)].compact.join('_')
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
def full_original_filename
|
|
203
|
+
[version_name, super].compact.join('_')
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
def cache_versions!(new_file)
|
|
207
|
+
# We might have processed the new_file argument after the callbacks were
|
|
208
|
+
# initialized, so get the actual file based off of the current state of
|
|
209
|
+
# our file
|
|
210
|
+
processed_parent = SanitizedFile.new :tempfile => self.file,
|
|
211
|
+
:filename => new_file.original_filename
|
|
212
|
+
|
|
213
|
+
active_versions.each do |name, v|
|
|
214
|
+
v.send(:cache_id=, cache_id)
|
|
215
|
+
v.cache!(processed_parent)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def store_versions!(new_file)
|
|
220
|
+
active_versions.each { |name, v| v.store!(new_file) }
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def remove_versions!
|
|
224
|
+
versions.each { |name, v| v.remove! }
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def retrieve_versions_from_cache!(cache_name)
|
|
228
|
+
versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def retrieve_versions_from_store!(identifier)
|
|
232
|
+
versions.each { |name, v| v.retrieve_from_store!(identifier) }
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
end # Versions
|
|
236
|
+
end # Uploader
|
|
237
|
+
end # CarrierWave
|