durran-carrierwave 0.3.2.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/Generators +4 -0
- data/History.txt +66 -0
- data/LICENSE +8 -0
- data/Manifest.txt +89 -0
- data/README.rdoc +342 -0
- data/Rakefile +30 -0
- data/carrierwave.gemspec +57 -0
- data/cucumber.yml +2 -0
- data/features/caching.feature +28 -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/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/file_steps.rb +42 -0
- data/features/step_definitions/general_steps.rb +80 -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 +35 -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.rb +145 -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 +332 -0
- data/lib/carrierwave/orm/activerecord.rb +73 -0
- data/lib/carrierwave/orm/datamapper.rb +27 -0
- data/lib/carrierwave/orm/mongomapper.rb +27 -0
- data/lib/carrierwave/orm/sequel.rb +57 -0
- data/lib/carrierwave/processing/image_science.rb +72 -0
- data/lib/carrierwave/processing/rmagick.rb +286 -0
- data/lib/carrierwave/sanitized_file.rb +272 -0
- data/lib/carrierwave/storage/abstract.rb +32 -0
- data/lib/carrierwave/storage/file.rb +50 -0
- data/lib/carrierwave/storage/s3.rb +215 -0
- data/lib/carrierwave/test/matchers.rb +114 -0
- data/lib/carrierwave/uploader.rb +43 -0
- data/lib/carrierwave/uploader/cache.rb +116 -0
- data/lib/carrierwave/uploader/callbacks.rb +42 -0
- data/lib/carrierwave/uploader/default_path.rb +23 -0
- data/lib/carrierwave/uploader/extension_whitelist.rb +37 -0
- data/lib/carrierwave/uploader/mountable.rb +39 -0
- data/lib/carrierwave/uploader/paths.rb +27 -0
- data/lib/carrierwave/uploader/processing.rb +81 -0
- data/lib/carrierwave/uploader/proxy.rb +62 -0
- data/lib/carrierwave/uploader/remove.rb +23 -0
- data/lib/carrierwave/uploader/store.rb +156 -0
- data/lib/carrierwave/uploader/url.rb +24 -0
- data/lib/carrierwave/uploader/versions.rb +147 -0
- data/lib/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 +43 -0
- data/spec/fixtures/bork.txt +1 -0
- data/spec/fixtures/test.jpeg +1 -0
- data/spec/fixtures/test.jpg +1 -0
- data/spec/mount_spec.rb +517 -0
- data/spec/orm/activerecord_spec.rb +271 -0
- data/spec/orm/datamapper_spec.rb +161 -0
- data/spec/orm/mongomapper_spec.rb +184 -0
- data/spec/orm/sequel_spec.rb +192 -0
- data/spec/sanitized_file_spec.rb +612 -0
- data/spec/spec_helper.rb +99 -0
- data/spec/uploader/cache_spec.rb +196 -0
- data/spec/uploader/default_path_spec.rb +68 -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 +62 -0
- data/spec/uploader/proxy_spec.rb +54 -0
- data/spec/uploader/remove_spec.rb +70 -0
- data/spec/uploader/store_spec.rb +274 -0
- data/spec/uploader/url_spec.rb +87 -0
- data/spec/uploader/versions_spec.rb +306 -0
- metadata +228 -0
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module Processing
|
6
|
+
|
7
|
+
depends_on CarrierWave::Uploader::Callbacks
|
8
|
+
|
9
|
+
setup do
|
10
|
+
after :cache, :process!
|
11
|
+
end
|
12
|
+
|
13
|
+
module ClassMethods
|
14
|
+
|
15
|
+
##
|
16
|
+
# Lists processor callbacks declared
|
17
|
+
#
|
18
|
+
# === Returns
|
19
|
+
#
|
20
|
+
# [Array[Array[Symbol, Array]]] a list of processor callbacks which have been declared for this uploader
|
21
|
+
#
|
22
|
+
def processors
|
23
|
+
@processors ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Adds a processor callback which applies operations as a file is uploaded.
|
28
|
+
# The argument may be the name of any method of the uploader, expressed as a symbol,
|
29
|
+
# or a list of such methods, or a hash where the key is a method and the value is
|
30
|
+
# an array of arguments to call the method with
|
31
|
+
#
|
32
|
+
# === Parameters
|
33
|
+
#
|
34
|
+
# args (*Symbol, Hash{Symbol => Array[]})
|
35
|
+
#
|
36
|
+
# === Examples
|
37
|
+
#
|
38
|
+
# class MyUploader < CarrierWave::Uploader::Base
|
39
|
+
#
|
40
|
+
# process :sepiatone, :vignette
|
41
|
+
# process :scale => [200, 200]
|
42
|
+
#
|
43
|
+
# def sepiatone
|
44
|
+
# ...
|
45
|
+
# end
|
46
|
+
#
|
47
|
+
# def vignette
|
48
|
+
# ...
|
49
|
+
# end
|
50
|
+
#
|
51
|
+
# def scale(height, width)
|
52
|
+
# ...
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
def process(*args)
|
57
|
+
args.each do |arg|
|
58
|
+
if arg.is_a?(Hash)
|
59
|
+
arg.each do |method, args|
|
60
|
+
processors.push([method, args])
|
61
|
+
end
|
62
|
+
else
|
63
|
+
processors.push([arg, []])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end # ClassMethods
|
69
|
+
|
70
|
+
##
|
71
|
+
# Apply all process callbacks added through CarrierWave.process
|
72
|
+
#
|
73
|
+
def process!(new_file=nil)
|
74
|
+
self.class.processors.each do |method, args|
|
75
|
+
self.send(method, *args)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end # Processing
|
80
|
+
end # Uploader
|
81
|
+
end # CarrierWave
|
@@ -0,0 +1,62 @@
|
|
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
|
+
end # Proxy
|
61
|
+
end # Uploader
|
62
|
+
end # CarrierWave
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module Remove
|
6
|
+
|
7
|
+
depends_on CarrierWave::Uploader::Callbacks
|
8
|
+
|
9
|
+
##
|
10
|
+
# Removes the file and reset it
|
11
|
+
#
|
12
|
+
def remove!
|
13
|
+
with_callbacks(:remove) do
|
14
|
+
CarrierWave.logger.info 'CarrierWave: removing file'
|
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,156 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module Store
|
6
|
+
|
7
|
+
depends_on CarrierWave::Uploader::Paths
|
8
|
+
depends_on CarrierWave::Uploader::Callbacks
|
9
|
+
depends_on CarrierWave::Uploader::Cache
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
|
13
|
+
##
|
14
|
+
# Sets the storage engine to be used when storing files with this uploader.
|
15
|
+
# Can be any class that implements a #store!(CarrierWave::SanitizedFile) and a #retrieve!
|
16
|
+
# method. See lib/carrierwave/storage/file.rb for an example. Storage engines should
|
17
|
+
# be added to CarrierWave.config[:storage_engines] so they can be referred
|
18
|
+
# to by a symbol, which should be more convenient
|
19
|
+
#
|
20
|
+
# If no argument is given, it will simply return the currently used storage engine.
|
21
|
+
#
|
22
|
+
# === Parameters
|
23
|
+
#
|
24
|
+
# [storage (Symbol, Class)] The storage engine to use for this uploader
|
25
|
+
#
|
26
|
+
# === Returns
|
27
|
+
#
|
28
|
+
# [Class] the storage engine to be used with this uploader
|
29
|
+
#
|
30
|
+
# === Examples
|
31
|
+
#
|
32
|
+
# storage :file
|
33
|
+
# storage CarrierWave::Storage::File
|
34
|
+
# storage MyCustomStorageEngine
|
35
|
+
#
|
36
|
+
def storage(storage = nil)
|
37
|
+
if storage.is_a?(Symbol)
|
38
|
+
@storage = get_storage_by_symbol(storage)
|
39
|
+
@storage.setup!
|
40
|
+
elsif storage
|
41
|
+
@storage = storage
|
42
|
+
@storage.setup!
|
43
|
+
elsif @storage.nil?
|
44
|
+
# Get the storage from the superclass if there is one
|
45
|
+
@storage = superclass.storage rescue nil
|
46
|
+
end
|
47
|
+
if @storage.nil?
|
48
|
+
# If we were not able to find a store any other way, setup the default store
|
49
|
+
@storage ||= get_storage_by_symbol(CarrierWave.config[:storage])
|
50
|
+
@storage.setup!
|
51
|
+
end
|
52
|
+
return @storage
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :storage=, :storage
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def get_storage_by_symbol(symbol)
|
60
|
+
eval(CarrierWave.config[:storage_engines][symbol])
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Override this in your Uploader to change the filename.
|
67
|
+
#
|
68
|
+
# Be careful using record ids as filenames. If the filename is stored in the database
|
69
|
+
# the record id will be nil when the filename is set. Don't use record ids unless you
|
70
|
+
# understand this limitation.
|
71
|
+
#
|
72
|
+
# Do not use the version_name in the filename, as it will prevent versions from being
|
73
|
+
# loaded correctly.
|
74
|
+
#
|
75
|
+
# === Returns
|
76
|
+
#
|
77
|
+
# [String] a filename
|
78
|
+
#
|
79
|
+
def filename
|
80
|
+
@filename
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# Override this in your Uploader to change the directory where the file backend stores files.
|
85
|
+
#
|
86
|
+
# Other backends may or may not use this method, depending on their specific needs.
|
87
|
+
#
|
88
|
+
# === Returns
|
89
|
+
#
|
90
|
+
# [String] a directory
|
91
|
+
#
|
92
|
+
def store_dir
|
93
|
+
CarrierWave.config[:store_dir]
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Calculates the path where the file should be stored. If +for_file+ is given, it will be
|
98
|
+
# used as the filename, otherwise +CarrierWave::Uploader#filename+ is assumed.
|
99
|
+
#
|
100
|
+
# === Parameters
|
101
|
+
#
|
102
|
+
# [for_file (String)] name of the file <optional>
|
103
|
+
#
|
104
|
+
# === Returns
|
105
|
+
#
|
106
|
+
# [String] the store path
|
107
|
+
#
|
108
|
+
def store_path(for_file=filename)
|
109
|
+
File.join(store_dir, full_filename(for_file))
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Stores the file by passing it to this Uploader's storage engine.
|
114
|
+
#
|
115
|
+
# If new_file is omitted, a previously cached file will be stored.
|
116
|
+
#
|
117
|
+
# === Parameters
|
118
|
+
#
|
119
|
+
# [new_file (File, IOString, Tempfile)] any kind of file object
|
120
|
+
#
|
121
|
+
def store!(new_file=nil)
|
122
|
+
cache!(new_file) if new_file
|
123
|
+
if @file and @cache_id
|
124
|
+
with_callbacks(:store, new_file) do
|
125
|
+
@file = storage.store!(@file)
|
126
|
+
@cache_id = nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Retrieves the file from the storage.
|
133
|
+
#
|
134
|
+
# === Parameters
|
135
|
+
#
|
136
|
+
# [identifier (String)] uniquely identifies the file to retrieve
|
137
|
+
#
|
138
|
+
def retrieve_from_store!(identifier)
|
139
|
+
with_callbacks(:retrieve_from_store, identifier) do
|
140
|
+
@file = storage.retrieve!(identifier)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def full_filename(for_file)
|
147
|
+
for_file
|
148
|
+
end
|
149
|
+
|
150
|
+
def storage
|
151
|
+
@storage ||= self.class.storage.new(self)
|
152
|
+
end
|
153
|
+
|
154
|
+
end # Store
|
155
|
+
end # Uploader
|
156
|
+
end # CarrierWave
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module Url
|
6
|
+
|
7
|
+
##
|
8
|
+
# === Returns
|
9
|
+
#
|
10
|
+
# [String] the location where this file is accessible via a url
|
11
|
+
#
|
12
|
+
def url
|
13
|
+
if file.respond_to?(:url) and not file.url.blank?
|
14
|
+
file.url
|
15
|
+
elsif current_path
|
16
|
+
File.expand_path(current_path).gsub(File.expand_path(public), '')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :to_s, :url
|
21
|
+
|
22
|
+
end # Url
|
23
|
+
end # Uploader
|
24
|
+
end # CarrierWave
|
@@ -0,0 +1,147 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module CarrierWave
|
4
|
+
module Uploader
|
5
|
+
module Versions
|
6
|
+
|
7
|
+
setup do
|
8
|
+
after :cache, :cache_versions!
|
9
|
+
after :store, :store_versions!
|
10
|
+
after :remove, :remove_versions!
|
11
|
+
after :retrieve_from_cache, :retrieve_versions_from_cache!
|
12
|
+
after :retrieve_from_store, :retrieve_versions_from_store!
|
13
|
+
end
|
14
|
+
|
15
|
+
module ClassMethods
|
16
|
+
|
17
|
+
def version_names
|
18
|
+
@version_names ||= []
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Adds a new version to this uploader
|
23
|
+
#
|
24
|
+
# === Parameters
|
25
|
+
#
|
26
|
+
# [name (#to_sym)] name of the version
|
27
|
+
# [&block (Proc)] a block to eval on this version of the uploader
|
28
|
+
#
|
29
|
+
def version(name, &block)
|
30
|
+
name = name.to_sym
|
31
|
+
unless versions[name]
|
32
|
+
versions[name] = Class.new(self)
|
33
|
+
versions[name].version_names.push(*version_names)
|
34
|
+
versions[name].version_names.push(name)
|
35
|
+
class_eval <<-RUBY
|
36
|
+
def #{name}
|
37
|
+
versions[:#{name}]
|
38
|
+
end
|
39
|
+
RUBY
|
40
|
+
end
|
41
|
+
versions[name].class_eval(&block) if block
|
42
|
+
versions[name]
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# === Returns
|
47
|
+
#
|
48
|
+
# [Hash{Symbol => Class}] a list of versions available for this uploader
|
49
|
+
#
|
50
|
+
def versions
|
51
|
+
@versions ||= {}
|
52
|
+
end
|
53
|
+
|
54
|
+
end # ClassMethods
|
55
|
+
|
56
|
+
##
|
57
|
+
# Returns a hash mapping the name of each version of the uploader to an instance of it
|
58
|
+
#
|
59
|
+
# === Returns
|
60
|
+
#
|
61
|
+
# [Hash{Symbol => CarrierWave::Uploader}] a list of uploader instances
|
62
|
+
#
|
63
|
+
def versions
|
64
|
+
return @versions if @versions
|
65
|
+
@versions = {}
|
66
|
+
self.class.versions.each do |name, klass|
|
67
|
+
@versions[name] = klass.new(model, mounted_as)
|
68
|
+
end
|
69
|
+
@versions
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# === Returns
|
74
|
+
#
|
75
|
+
# [String] the name of this version of the uploader
|
76
|
+
#
|
77
|
+
def version_name
|
78
|
+
self.class.version_names.join('_').to_sym unless self.class.version_names.blank?
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# When given a version name as a parameter, will return the url for that version
|
83
|
+
# This also works with nested versions.
|
84
|
+
#
|
85
|
+
# === Example
|
86
|
+
#
|
87
|
+
# my_uploader.url # => /path/to/my/uploader.gif
|
88
|
+
# my_uploader.url(:thumb) # => /path/to/my/thumb_uploader.gif
|
89
|
+
# my_uploader.url(:thumb, :small) # => /path/to/my/thumb_small_uploader.gif
|
90
|
+
#
|
91
|
+
# === Parameters
|
92
|
+
#
|
93
|
+
# [*args (Symbol)] any number of versions
|
94
|
+
#
|
95
|
+
# === Returns
|
96
|
+
#
|
97
|
+
# [String] the location where this file is accessible via a url
|
98
|
+
#
|
99
|
+
def url(*args)
|
100
|
+
if(args.first)
|
101
|
+
raise ArgumentError, "Version #{args.first} doesn't exist!" if versions[args.first.to_sym].nil?
|
102
|
+
# recursively proxy to version
|
103
|
+
versions[args.first.to_sym].url(*args[1..-1])
|
104
|
+
else
|
105
|
+
super()
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
def full_filename(for_file)
|
112
|
+
[version_name, super(for_file)].compact.join('_')
|
113
|
+
end
|
114
|
+
|
115
|
+
def full_original_filename
|
116
|
+
[version_name, super].compact.join('_')
|
117
|
+
end
|
118
|
+
|
119
|
+
def cache_versions!(new_file)
|
120
|
+
versions.each do |name, v|
|
121
|
+
v.send(:cache_id=, cache_id)
|
122
|
+
v.cache!(new_file)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def store_versions!(new_file)
|
127
|
+
versions.each { |name, v| v.store!(new_file) }
|
128
|
+
end
|
129
|
+
|
130
|
+
def remove_versions!
|
131
|
+
versions.each do |name, v|
|
132
|
+
CarrierWave.logger.info "CarrierWave: removing file for version #{v.version_name}"
|
133
|
+
v.remove!
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def retrieve_versions_from_cache!(cache_name)
|
138
|
+
versions.each { |name, v| v.retrieve_from_cache!(cache_name) }
|
139
|
+
end
|
140
|
+
|
141
|
+
def retrieve_versions_from_store!(identifier)
|
142
|
+
versions.each { |name, v| v.retrieve_from_store!(identifier) }
|
143
|
+
end
|
144
|
+
|
145
|
+
end # Versions
|
146
|
+
end # Uploader
|
147
|
+
end # CarrierWave
|