dragonfly 0.1.1 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of dragonfly might be problematic. Click here for more details.
- data/Rakefile +10 -0
- data/VERSION +1 -1
- data/docs.watchr +1 -0
- data/dragonfly-rails.gemspec +2 -2
- data/dragonfly.gemspec +5 -3
- data/features/steps/dragonfly_steps.rb +1 -1
- data/lib/dragonfly/active_record_extensions/attachment.rb +1 -1
- data/lib/dragonfly/analysis/file_command_analyser.rb +21 -0
- data/lib/dragonfly/app.rb +101 -9
- data/lib/dragonfly/data_storage/file_data_store.rb +8 -8
- data/lib/dragonfly/encoding/transparent_encoder.rb +14 -0
- data/lib/dragonfly/r_magick_configuration.rb +56 -55
- data/lib/dragonfly/rails/images.rb +1 -1
- data/lib/dragonfly/temp_object.rb +6 -0
- data/spec/dragonfly/active_record_extensions/migration.rb +2 -1
- data/spec/dragonfly/active_record_extensions/model_spec.rb +7 -0
- data/spec/dragonfly/app_spec.rb +20 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +17 -3
- data/spec/dragonfly/temp_object_spec.rb +18 -0
- metadata +5 -3
- data/lib/dragonfly/app_configuration.rb +0 -9
data/Rakefile
CHANGED
@@ -39,6 +39,16 @@ Rake::RDocTask.new do |rdoc|
|
|
39
39
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
40
40
|
end
|
41
41
|
|
42
|
+
require 'yard'
|
43
|
+
YARD::Rake::YardocTask.new do |t|
|
44
|
+
t.files = ['lib/**/*.rb']
|
45
|
+
t.options = %w(--no-private)
|
46
|
+
end
|
47
|
+
YARD::Rake::YardocTask.new 'yard:changed' do |t|
|
48
|
+
t.files = `git stat | grep '.rb' | grep modified | cut -d' ' -f4`.split
|
49
|
+
t.options = %w(--no-private)
|
50
|
+
end
|
51
|
+
|
42
52
|
require 'spec/rake/spectask'
|
43
53
|
Spec::Rake::SpecTask.new(:spec) do |t|
|
44
54
|
t.libs << 'lib' << 'spec'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.4
|
data/docs.watchr
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
watch( 'lib/.*\.rb' ) {|md| system("rake yard:changed") }
|
data/dragonfly-rails.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dragonfly-rails}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Mark Evans"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-18}
|
13
13
|
s.email = %q{mark@new-bamboo.co.uk}
|
14
14
|
s.homepage = %q{http://github.com/markevans/dragonfly}
|
15
15
|
s.rdoc_options = ["--charset=UTF-8"]
|
data/dragonfly.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dragonfly}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Mark Evans"]
|
12
|
-
s.date = %q{2009-11-
|
12
|
+
s.date = %q{2009-11-18}
|
13
13
|
s.email = %q{mark@new-bamboo.co.uk}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
|
|
23
23
|
"VERSION",
|
24
24
|
"config.rb",
|
25
25
|
"config.ru",
|
26
|
+
"docs.watchr",
|
26
27
|
"dragonfly-rails.gemspec",
|
27
28
|
"dragonfly.gemspec",
|
28
29
|
"features/dragonfly.feature",
|
@@ -44,9 +45,9 @@ Gem::Specification.new do |s|
|
|
44
45
|
"lib/dragonfly/active_record_extensions/validations.rb",
|
45
46
|
"lib/dragonfly/analysis/analyser.rb",
|
46
47
|
"lib/dragonfly/analysis/base.rb",
|
48
|
+
"lib/dragonfly/analysis/file_command_analyser.rb",
|
47
49
|
"lib/dragonfly/analysis/r_magick_analyser.rb",
|
48
50
|
"lib/dragonfly/app.rb",
|
49
|
-
"lib/dragonfly/app_configuration.rb",
|
50
51
|
"lib/dragonfly/configurable.rb",
|
51
52
|
"lib/dragonfly/core_ext/object.rb",
|
52
53
|
"lib/dragonfly/data_storage.rb",
|
@@ -56,6 +57,7 @@ Gem::Specification.new do |s|
|
|
56
57
|
"lib/dragonfly/data_storage/transparent_data_store.rb",
|
57
58
|
"lib/dragonfly/encoding/base.rb",
|
58
59
|
"lib/dragonfly/encoding/r_magick_encoder.rb",
|
60
|
+
"lib/dragonfly/encoding/transparent_encoder.rb",
|
59
61
|
"lib/dragonfly/extended_temp_object.rb",
|
60
62
|
"lib/dragonfly/middleware.rb",
|
61
63
|
"lib/dragonfly/middleware_with_cache.rb",
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Given /^a stored image "(.+?)" with dimensions (\d+)x(\d+)$/ do |name, width, height|
|
2
2
|
tempfile = Tempfile.new(name)
|
3
3
|
`convert -resize #{width}x#{height}! #{SAMPLE_IMAGE_PATH} #{tempfile.path}`
|
4
|
-
temp_object = APP.
|
4
|
+
temp_object = APP.create_object(tempfile)
|
5
5
|
uid = APP.datastore.store(temp_object)
|
6
6
|
TEMP_IMAGES[name] = uid
|
7
7
|
end
|
@@ -97,7 +97,7 @@ module Dragonfly
|
|
97
97
|
def magic_attributes
|
98
98
|
parent_model.class.column_names.select { |name|
|
99
99
|
name =~ /^#{attribute_name}_(.+)$/ &&
|
100
|
-
analyser.has_analysis_method?($1) || $1
|
100
|
+
(analyser.has_analysis_method?($1) || %w(size ext).include?($1))
|
101
101
|
}
|
102
102
|
end
|
103
103
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rmagick'
|
2
|
+
require 'mime/types'
|
3
|
+
|
4
|
+
module Dragonfly
|
5
|
+
module Analysis
|
6
|
+
|
7
|
+
class FileCommandAnalyser < Base
|
8
|
+
|
9
|
+
include Configurable
|
10
|
+
|
11
|
+
configurable_attr :file_command do `which file`.chomp end
|
12
|
+
|
13
|
+
def mime_type(temp_object)
|
14
|
+
output = `#{file_command} -b --mime #{temp_object.path}`
|
15
|
+
output.split(';').first
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/dragonfly/app.rb
CHANGED
@@ -2,12 +2,63 @@ require 'logger'
|
|
2
2
|
require 'forwardable'
|
3
3
|
|
4
4
|
module Dragonfly
|
5
|
+
|
6
|
+
# A Dragonfly App is the rack app which holds everything together.
|
7
|
+
# You can have as many app instances as you want, and they all have
|
8
|
+
# completely separate configuration.
|
9
|
+
# Each App has a name.
|
10
|
+
# @example
|
11
|
+
# Dragonfly::App[:images] # => creates a new app named :images
|
12
|
+
# Dragonfly::App[:images] # => returns the :images app
|
13
|
+
# Dragonfly::App[:ocr] # => creates a new app named :ocr
|
14
|
+
#
|
15
|
+
# # The two apps can be differently configured
|
16
|
+
# Dragonfly::App[:images].parameters.default_format = :jpg
|
17
|
+
# Dragonfly::App[:ocr].parameters.default_format = :tif
|
18
|
+
#
|
19
|
+
# @example Example configuration options:
|
20
|
+
#
|
21
|
+
# Dragonfly::App[:images].configure do |c|
|
22
|
+
# c.datastore = MyEC2DataStore.new # See DataStorage::Base for how to create a custom data store
|
23
|
+
# c.encoder = Encoding::RMagickEncoder.new # See Encoding::Base for how to create a custom encoder
|
24
|
+
# c.log = Logger.new('/tmp/my.log')
|
25
|
+
# c.cache_duration = 3000 # seconds
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# @example Configuration including nested items
|
29
|
+
#
|
30
|
+
# Dragonfly::App[:images].configure do |c|
|
31
|
+
# # ...
|
32
|
+
# c.datastore.configure do |d| # configuration depends on which data store you use
|
33
|
+
# # ...
|
34
|
+
# end
|
35
|
+
# c.analyser.configure do |a| # see Analysis::Analyser
|
36
|
+
# # ...
|
37
|
+
# end
|
38
|
+
# c.processor.configure do |p| # see Processing::Processor
|
39
|
+
# # ...
|
40
|
+
# end
|
41
|
+
# c.parameters.configure do |p| # see Parameters (class methods)
|
42
|
+
# # ...
|
43
|
+
# end
|
44
|
+
# c.url_handler.configure do |u| # see UrlHandler
|
45
|
+
# # ...
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
5
49
|
class App
|
6
50
|
|
51
|
+
|
7
52
|
class << self
|
8
53
|
|
9
54
|
private :new # Hide 'new' - need to use 'instance'
|
10
55
|
|
56
|
+
# Get / create a Dragonfly App.
|
57
|
+
#
|
58
|
+
# Rather than using 'new', use this method to create / refer to each app.
|
59
|
+
#
|
60
|
+
# @param [Symbol] name the name of the App
|
61
|
+
# @return [App] either the named App or a new one with that name
|
11
62
|
def instance(name)
|
12
63
|
apps[name] ||= new
|
13
64
|
end
|
@@ -30,16 +81,19 @@ module Dragonfly
|
|
30
81
|
initialize_temp_object_class
|
31
82
|
end
|
32
83
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
84
|
+
# @see Analysis::Analyser
|
85
|
+
attr_reader :analyser
|
86
|
+
# @see Processing::Processor
|
87
|
+
attr_reader :processor
|
88
|
+
# @see Encoding::Base
|
89
|
+
attr_reader :encoder
|
90
|
+
# @see UrlHandler
|
91
|
+
attr_reader :url_handler
|
92
|
+
# @see Parameters
|
93
|
+
attr_reader :parameters_class
|
39
94
|
|
40
95
|
alias parameters parameters_class
|
41
96
|
|
42
|
-
# Just for convenience so the user doesn't have to use url_handler
|
43
97
|
extend Forwardable
|
44
98
|
def_delegator :url_handler, :url_for
|
45
99
|
|
@@ -48,13 +102,26 @@ module Dragonfly
|
|
48
102
|
configurable_attr :datastore do DataStorage::FileDataStore.new end
|
49
103
|
configurable_attr :encoder do Encoding::Base.new end
|
50
104
|
configurable_attr :log do Logger.new('/var/tmp/dragonfly.log') end
|
51
|
-
configurable_attr :cache_duration,
|
105
|
+
configurable_attr :cache_duration, 3600*24*365 # Defaults to 1 year
|
106
|
+
configurable_attr :fallback_mime_type, 'application/octet-stream'
|
52
107
|
|
108
|
+
# The call method required by Rack to run.
|
109
|
+
#
|
110
|
+
# @param env the Rack env hash
|
111
|
+
# @return [Array] a Rack response:
|
112
|
+
#
|
113
|
+
# - 200 status if all ok
|
114
|
+
#
|
115
|
+
# - 400 if url recognised but parameters incorrect
|
116
|
+
#
|
117
|
+
# - 404 if url not recognised / data not found.
|
118
|
+
#
|
119
|
+
# See the Rack documentation for more details
|
53
120
|
def call(env)
|
54
121
|
parameters = url_handler.url_to_parameters(env['PATH_INFO'], env['QUERY_STRING'])
|
55
122
|
temp_object = fetch(parameters.uid, parameters)
|
56
123
|
[200, {
|
57
|
-
"Content-Type" => temp_object.mime_type,
|
124
|
+
"Content-Type" => temp_object.mime_type || fallback_mime_type,
|
58
125
|
"Content-Length" => temp_object.size.to_s,
|
59
126
|
"ETag" => parameters.unique_signature,
|
60
127
|
"Cache-Control" => "public, max-age=#{cache_duration}"
|
@@ -65,17 +132,42 @@ module Dragonfly
|
|
65
132
|
[404, {"Content-Type" => 'text/plain'}, [e.message]]
|
66
133
|
end
|
67
134
|
|
135
|
+
# Store an object, using the configured datastore
|
136
|
+
# @param [String, File, Tempfile, TempObject] object the object holding the data
|
137
|
+
# @return [String] the uid assigned to it
|
138
|
+
def store(object)
|
139
|
+
datastore.store(create_object(object))
|
140
|
+
end
|
141
|
+
|
142
|
+
# Fetch an object from the database and optionally transform
|
143
|
+
#
|
144
|
+
# Note that the arguments passed in to transform are as defined by the
|
145
|
+
# parameter shortcuts (see Parameter class methods)
|
146
|
+
# @param [String] uid the string uid corresponding to the stored data object
|
147
|
+
# @param [*args [optional]] shortcut_args the shortcut args for transforming the object
|
148
|
+
# @return [ExtendedTempObject] a temp_object holding the data
|
149
|
+
# @example
|
150
|
+
# app = Dragonfly::App[:images]
|
151
|
+
# app.fetch('abcd1234') # returns a temp_object with exactly the data that was originally stored
|
152
|
+
# app.fetch('abcd1234', '20x20!') # returns a transformed temp_object, in this case with image data resized to 20x20
|
153
|
+
# @see Parameters
|
68
154
|
def fetch(uid, *args)
|
69
155
|
temp_object = temp_object_class.new(datastore.retrieve(uid))
|
70
156
|
temp_object.transform(*args)
|
71
157
|
end
|
72
158
|
|
159
|
+
# Create a temp_object from the object passed in
|
160
|
+
# @param [String, File, Tempfile, TempObject] initialization_object the object holding the data
|
161
|
+
# @return [ExtendedTempObject] a temp_object holding the data
|
73
162
|
def create_object(initialization_object)
|
74
163
|
temp_object_class.new(initialization_object)
|
75
164
|
end
|
76
165
|
|
77
166
|
private
|
78
167
|
|
168
|
+
# @private
|
169
|
+
attr_reader :temp_object_class
|
170
|
+
|
79
171
|
def initialize_temp_object_class
|
80
172
|
@temp_object_class = Class.new(ExtendedTempObject)
|
81
173
|
@temp_object_class.app = self
|
@@ -12,7 +12,7 @@ module Dragonfly
|
|
12
12
|
suffix = if temp_object.name.blank?
|
13
13
|
'file'
|
14
14
|
else
|
15
|
-
temp_object.name
|
15
|
+
temp_object.name
|
16
16
|
end
|
17
17
|
relative_path = relative_storage_path(suffix)
|
18
18
|
|
@@ -26,15 +26,15 @@ module Dragonfly
|
|
26
26
|
raise UnableToStore, e.message
|
27
27
|
end
|
28
28
|
|
29
|
-
relative_path
|
29
|
+
relative_path.sub(/\.[^.]*?$/, '')
|
30
30
|
end
|
31
31
|
|
32
|
-
def retrieve(
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
32
|
+
def retrieve(uid)
|
33
|
+
entries = Dir[absolute_storage_path(uid) + '*']
|
34
|
+
raise DataNotFound if entries.empty?
|
35
|
+
File.new(entries.first)
|
36
|
+
rescue Errno::ENOENT => e
|
37
|
+
raise DataNotFound, e.message
|
38
38
|
end
|
39
39
|
|
40
40
|
def destroy(relative_path)
|
@@ -1,62 +1,63 @@
|
|
1
1
|
module Dragonfly
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
a.register(Analysis::RMagickAnalyser.new)
|
9
|
-
end
|
10
|
-
c.processor do |p|
|
11
|
-
p.register(Processing::RMagickProcessor)
|
12
|
-
end
|
13
|
-
c.encoder = Encoding::RMagickEncoder.new
|
14
|
-
c.parameters do |p|
|
15
|
-
p.default_format = :jpg
|
16
|
-
# Standard resizing like '30x40!', etc.
|
17
|
-
p.add_shortcut(Symbol) do |format|
|
18
|
-
{:format => format}
|
19
|
-
end
|
20
|
-
p.add_shortcut(/^\d*x\d*[><%^!]?$|^\d+@$/) do |geometry, match_data|
|
21
|
-
{
|
22
|
-
:processing_method => :resize,
|
23
|
-
:processing_options => {:geometry => geometry}
|
24
|
-
}
|
2
|
+
module RMagickConfiguration
|
3
|
+
|
4
|
+
def self.apply_configuration(app)
|
5
|
+
app.configure do |c|
|
6
|
+
c.analyser do |a|
|
7
|
+
a.register(Analysis::RMagickAnalyser.new)
|
25
8
|
end
|
26
|
-
|
27
|
-
|
28
|
-
{
|
29
|
-
:processing_method => :resize_and_crop,
|
30
|
-
:processing_options => {:width => match_data[1], :height => match_data[2], :gravity => match_data[3]}
|
31
|
-
}
|
9
|
+
c.processor do |p|
|
10
|
+
p.register(Processing::RMagickProcessor)
|
32
11
|
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
:
|
12
|
+
c.encoder = Encoding::RMagickEncoder.new
|
13
|
+
c.parameters do |p|
|
14
|
+
p.default_format = :jpg
|
15
|
+
# Standard resizing like '30x40!', etc.
|
16
|
+
p.add_shortcut(Symbol) do |format|
|
17
|
+
{:format => format}
|
18
|
+
end
|
19
|
+
p.add_shortcut(/^\d*x\d*[><%^!]?$|^\d+@$/) do |geometry, match_data|
|
20
|
+
{
|
21
|
+
:processing_method => :resize,
|
22
|
+
:processing_options => {:geometry => geometry}
|
43
23
|
}
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
}
|
54
|
-
|
55
|
-
|
56
|
-
|
24
|
+
end
|
25
|
+
# Cropped resizing like '20x50#ne'
|
26
|
+
p.add_shortcut(/^(\d+)x(\d+)#(\w{1,2})?/) do |geometry, match_data|
|
27
|
+
{
|
28
|
+
:processing_method => :resize_and_crop,
|
29
|
+
:processing_options => {:width => match_data[1], :height => match_data[2], :gravity => match_data[3]}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
# Cropping like '30x30+10+10ne'
|
33
|
+
p.add_shortcut(/^(\d+)x(\d+)([+-]\d+)([+-]\d+)(\w{1,2})?/) do |geometry, match_data|
|
34
|
+
{
|
35
|
+
:processing_method => :crop,
|
36
|
+
:processing_options => {
|
37
|
+
:width => match_data[1],
|
38
|
+
:height => match_data[2],
|
39
|
+
:x => match_data[3],
|
40
|
+
:y => match_data[4],
|
41
|
+
:gravity => match_data[5]
|
42
|
+
}
|
43
|
+
}
|
44
|
+
end
|
45
|
+
p.add_shortcut(/^\d*x/, Symbol) do |geometry, format|
|
46
|
+
p.hash_from_shortcut(geometry).merge(:format => format)
|
47
|
+
end
|
48
|
+
p.add_shortcut(:rotate, Numeric) do |_, amount|
|
49
|
+
{
|
50
|
+
:processing_method => :rotate,
|
51
|
+
:processing_options => {:amount => amount, :background_colour => '#0000'}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
p.add_shortcut(:rotate, Numeric, Symbol) do |a, b, format|
|
55
|
+
p.hash_from_shortcut(a,b).merge(:format => format)
|
56
|
+
end
|
57
57
|
end
|
58
58
|
end
|
59
|
+
|
59
60
|
end
|
60
|
-
|
61
|
-
|
62
|
-
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
@@ -5,7 +5,8 @@ class MigrationForTest < ActiveRecord::Migration
|
|
5
5
|
t.string :title
|
6
6
|
t.string :preview_image_uid
|
7
7
|
t.string :preview_image_some_analyser_method
|
8
|
-
t.integer
|
8
|
+
t.integer :preview_image_size
|
9
|
+
t.string :preview_image_ext
|
9
10
|
t.string :preview_image_blah_blah
|
10
11
|
t.string :other_image_uid
|
11
12
|
t.string :yet_another_image_uid
|
@@ -395,6 +395,13 @@ describe Item do
|
|
395
395
|
@item.preview_image_size.should == 3
|
396
396
|
end
|
397
397
|
|
398
|
+
it "should store the original file extension if it exists" do
|
399
|
+
data = 'jasdlkf sadjl'
|
400
|
+
data.stub!(:original_filename).and_return('hello.png')
|
401
|
+
@item.preview_image = data
|
402
|
+
@item.preview_image_ext.should == 'png'
|
403
|
+
end
|
404
|
+
|
398
405
|
end
|
399
406
|
|
400
407
|
end
|
data/spec/dragonfly/app_spec.rb
CHANGED
@@ -66,4 +66,24 @@ describe Dragonfly::App do
|
|
66
66
|
|
67
67
|
end
|
68
68
|
|
69
|
+
describe "mime types" do
|
70
|
+
before(:each) do
|
71
|
+
@app = Dragonfly::App[:images]
|
72
|
+
@app.url_handler.protect_from_dos_attacks = false
|
73
|
+
@app.fallback_mime_type = 'egg/heads'
|
74
|
+
@temp_object = Dragonfly::TempObject.new('GOOG')
|
75
|
+
@app.stub!(:fetch).and_return(@temp_object)
|
76
|
+
end
|
77
|
+
it "should use the temp object mime-type" do
|
78
|
+
@temp_object.should_receive(:mime_type).and_return 'my/type'
|
79
|
+
response = make_request(@app, 'hello.png')
|
80
|
+
response.headers['Content-Type'].should == 'my/type'
|
81
|
+
end
|
82
|
+
it "should use the app's fallback mime-type if the temp_object one isn't known" do
|
83
|
+
@temp_object.should_receive(:mime_type).and_return nil
|
84
|
+
response = make_request(@app, 'hello.png')
|
85
|
+
response.headers['Content-Type'].should == 'egg/heads'
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
69
89
|
end
|
@@ -56,9 +56,9 @@ describe Dragonfly::DataStorage::FileDataStore do
|
|
56
56
|
@data_store.store(@temp_object)
|
57
57
|
end
|
58
58
|
|
59
|
-
it "should use the
|
59
|
+
it "should use the entire temp_object name including extension if it exists" do
|
60
60
|
@temp_object.name = 'hello.you.png'
|
61
|
-
it_should_write_to_file("#{@file_pattern_prefix}_hello.you", @temp_object)
|
61
|
+
it_should_write_to_file("#{@file_pattern_prefix}_hello.you.png", @temp_object)
|
62
62
|
@data_store.store(@temp_object)
|
63
63
|
end
|
64
64
|
|
@@ -68,10 +68,15 @@ describe Dragonfly::DataStorage::FileDataStore do
|
|
68
68
|
@data_store.store(@temp_object)
|
69
69
|
end
|
70
70
|
|
71
|
-
it "should return the filepath without the root of the stored file" do
|
71
|
+
it "should return the filepath without the root of the stored file when a file name is not provided" do
|
72
72
|
@data_store.store(@temp_object).should == "#{@file_pattern_prefix_without_root}_file"
|
73
73
|
end
|
74
74
|
|
75
|
+
it "should return the filepath without the root of the stored file when a file name is provided" do
|
76
|
+
@temp_object.name = 'hello.you.png'
|
77
|
+
@data_store.store(@temp_object).should == "#{@file_pattern_prefix_without_root}_hello.you"
|
78
|
+
end
|
79
|
+
|
75
80
|
it "should raise an error if it can't create a directory" do
|
76
81
|
FileUtils.should_receive(:mkdir_p).and_raise(Errno::EACCES)
|
77
82
|
lambda{ @data_store.store(@temp_object) }.should raise_error(Dragonfly::DataStorage::UnableToStore)
|
@@ -88,6 +93,15 @@ describe Dragonfly::DataStorage::FileDataStore do
|
|
88
93
|
@data_store.root_path.should be_an_empty_directory
|
89
94
|
end
|
90
95
|
|
96
|
+
describe "retrieving" do
|
97
|
+
it "should retrieve the correct file even though the extension isn't given" do
|
98
|
+
@temp_object.name = 'hello.there'
|
99
|
+
uid = @data_store.store(@temp_object)
|
100
|
+
uid.should =~ /_hello$/
|
101
|
+
Dragonfly::TempObject.new(@data_store.retrieve(uid)).data.should == @temp_object.data
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
91
105
|
end
|
92
106
|
|
93
107
|
end
|
@@ -230,4 +230,22 @@ describe Dragonfly::TempObject do
|
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
233
|
+
describe "ext" do
|
234
|
+
before(:each) do
|
235
|
+
@temp_object = Dragonfly::TempObject.new('asfsadf')
|
236
|
+
end
|
237
|
+
it "should use the correct extension from name" do
|
238
|
+
@temp_object.name = 'hello.there.mate'
|
239
|
+
@temp_object.ext.should == 'mate'
|
240
|
+
end
|
241
|
+
it "should be nil if name has none" do
|
242
|
+
@temp_object.name = 'hello'
|
243
|
+
@temp_object.ext.should be_nil
|
244
|
+
end
|
245
|
+
it "should be nil if name is nil" do
|
246
|
+
@temp_object.name = nil
|
247
|
+
@temp_object.ext.should be_nil
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
233
251
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dragonfly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mark Evans
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-18 00:00:00 +00:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- VERSION
|
40
40
|
- config.rb
|
41
41
|
- config.ru
|
42
|
+
- docs.watchr
|
42
43
|
- dragonfly-rails.gemspec
|
43
44
|
- dragonfly.gemspec
|
44
45
|
- features/dragonfly.feature
|
@@ -60,9 +61,9 @@ files:
|
|
60
61
|
- lib/dragonfly/active_record_extensions/validations.rb
|
61
62
|
- lib/dragonfly/analysis/analyser.rb
|
62
63
|
- lib/dragonfly/analysis/base.rb
|
64
|
+
- lib/dragonfly/analysis/file_command_analyser.rb
|
63
65
|
- lib/dragonfly/analysis/r_magick_analyser.rb
|
64
66
|
- lib/dragonfly/app.rb
|
65
|
-
- lib/dragonfly/app_configuration.rb
|
66
67
|
- lib/dragonfly/configurable.rb
|
67
68
|
- lib/dragonfly/core_ext/object.rb
|
68
69
|
- lib/dragonfly/data_storage.rb
|
@@ -72,6 +73,7 @@ files:
|
|
72
73
|
- lib/dragonfly/data_storage/transparent_data_store.rb
|
73
74
|
- lib/dragonfly/encoding/base.rb
|
74
75
|
- lib/dragonfly/encoding/r_magick_encoder.rb
|
76
|
+
- lib/dragonfly/encoding/transparent_encoder.rb
|
75
77
|
- lib/dragonfly/extended_temp_object.rb
|
76
78
|
- lib/dragonfly/middleware.rb
|
77
79
|
- lib/dragonfly/middleware_with_cache.rb
|