oahu-dragonfly 0.8.2
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/.rspec +1 -0
- data/.yardopts +24 -0
- data/Gemfile +30 -0
- data/History.md +323 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/config.ru +14 -0
- data/docs.watchr +1 -0
- data/dragonfly.gemspec +297 -0
- data/extra_docs/Analysers.md +66 -0
- data/extra_docs/Caching.md +23 -0
- data/extra_docs/Configuration.md +124 -0
- data/extra_docs/Couch.md +49 -0
- data/extra_docs/DataStorage.md +153 -0
- data/extra_docs/Encoding.md +67 -0
- data/extra_docs/GeneralUsage.md +121 -0
- data/extra_docs/Generators.md +60 -0
- data/extra_docs/Heroku.md +50 -0
- data/extra_docs/ImageMagick.md +125 -0
- data/extra_docs/Index.md +33 -0
- data/extra_docs/MimeTypes.md +40 -0
- data/extra_docs/Models.md +272 -0
- data/extra_docs/Mongo.md +45 -0
- data/extra_docs/Processing.md +77 -0
- data/extra_docs/Rack.md +52 -0
- data/extra_docs/Rails2.md +57 -0
- data/extra_docs/Rails3.md +62 -0
- data/extra_docs/Sinatra.md +25 -0
- data/extra_docs/URLs.md +169 -0
- data/features/images.feature +47 -0
- data/features/no_processing.feature +14 -0
- data/features/rails_3.0.5.feature +8 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +66 -0
- data/features/steps/rails_steps.rb +28 -0
- data/features/support/env.rb +13 -0
- data/features/support/setup.rb +32 -0
- data/fixtures/rails_3.0.5/files/app/models/album.rb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/show.html.erb +6 -0
- data/fixtures/rails_3.0.5/files/config/initializers/dragonfly.rb +4 -0
- data/fixtures/rails_3.0.5/files/features/manage_album_images.feature +38 -0
- data/fixtures/rails_3.0.5/files/features/step_definitions/helper_steps.rb +7 -0
- data/fixtures/rails_3.0.5/files/features/step_definitions/image_steps.rb +25 -0
- data/fixtures/rails_3.0.5/files/features/support/paths.rb +17 -0
- data/fixtures/rails_3.0.5/files/features/text_images.feature +7 -0
- data/fixtures/rails_3.0.5/template.rb +20 -0
- data/irbrc.rb +18 -0
- data/lib/dragonfly.rb +55 -0
- data/lib/dragonfly/active_model_extensions.rb +13 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +250 -0
- data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +148 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +95 -0
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_model_extensions/validations.rb +41 -0
- data/lib/dragonfly/analyser.rb +58 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
- data/lib/dragonfly/analysis/image_magick_analyser.rb +6 -0
- data/lib/dragonfly/app.rb +172 -0
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/image_magick.rb +6 -0
- data/lib/dragonfly/config/rails.rb +20 -0
- data/lib/dragonfly/configurable.rb +207 -0
- data/lib/dragonfly/core_ext/array.rb +7 -0
- data/lib/dragonfly/core_ext/hash.rb +7 -0
- data/lib/dragonfly/core_ext/object.rb +12 -0
- data/lib/dragonfly/core_ext/string.rb +9 -0
- data/lib/dragonfly/core_ext/symbol.rb +9 -0
- data/lib/dragonfly/data_storage.rb +9 -0
- data/lib/dragonfly/data_storage/couch_data_store.rb +64 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +141 -0
- data/lib/dragonfly/data_storage/mongo_data_store.rb +86 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +145 -0
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/image_magick_encoder.rb +6 -0
- data/lib/dragonfly/function_manager.rb +71 -0
- data/lib/dragonfly/generation/image_magick_generator.rb +6 -0
- data/lib/dragonfly/generator.rb +9 -0
- data/lib/dragonfly/hash_with_css_style_keys.rb +21 -0
- data/lib/dragonfly/image_magick/analyser.rb +51 -0
- data/lib/dragonfly/image_magick/config.rb +41 -0
- data/lib/dragonfly/image_magick/encoder.rb +57 -0
- data/lib/dragonfly/image_magick/generator.rb +145 -0
- data/lib/dragonfly/image_magick/processor.rb +99 -0
- data/lib/dragonfly/image_magick/utils.rb +72 -0
- data/lib/dragonfly/image_magick_utils.rb +4 -0
- data/lib/dragonfly/job.rb +451 -0
- data/lib/dragonfly/job_builder.rb +39 -0
- data/lib/dragonfly/job_definitions.rb +26 -0
- data/lib/dragonfly/job_endpoint.rb +15 -0
- data/lib/dragonfly/loggable.rb +28 -0
- data/lib/dragonfly/middleware.rb +20 -0
- data/lib/dragonfly/processing/image_magick_processor.rb +6 -0
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/rails/images.rb +27 -0
- data/lib/dragonfly/response.rb +97 -0
- data/lib/dragonfly/routed_endpoint.rb +40 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/server.rb +113 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/temp_object.rb +175 -0
- data/lib/dragonfly/url_mapper.rb +78 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/spec/dragonfly/active_model_extensions/model_spec.rb +1426 -0
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +91 -0
- data/spec/dragonfly/analyser_spec.rb +123 -0
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +48 -0
- data/spec/dragonfly/app_spec.rb +135 -0
- data/spec/dragonfly/configurable_spec.rb +461 -0
- data/spec/dragonfly/core_ext/array_spec.rb +19 -0
- data/spec/dragonfly/core_ext/hash_spec.rb +19 -0
- data/spec/dragonfly/core_ext/string_spec.rb +17 -0
- data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
- data/spec/dragonfly/data_storage/couch_data_store_spec.rb +76 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +296 -0
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +57 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +258 -0
- data/spec/dragonfly/data_storage/shared_data_store_examples.rb +77 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/hash_with_css_style_keys_spec.rb +24 -0
- data/spec/dragonfly/image_magick/analyser_spec.rb +64 -0
- data/spec/dragonfly/image_magick/encoder_spec.rb +41 -0
- data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
- data/spec/dragonfly/image_magick/processor_spec.rb +233 -0
- data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
- data/spec/dragonfly/job_builder_spec.rb +37 -0
- data/spec/dragonfly/job_definitions_spec.rb +35 -0
- data/spec/dragonfly/job_endpoint_spec.rb +173 -0
- data/spec/dragonfly/job_spec.rb +1046 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +47 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
- data/spec/dragonfly/serializer_spec.rb +61 -0
- data/spec/dragonfly/server_spec.rb +278 -0
- data/spec/dragonfly/simple_cache_spec.rb +27 -0
- data/spec/dragonfly/temp_object_spec.rb +306 -0
- data/spec/dragonfly/url_mapper_spec.rb +126 -0
- data/spec/functional/deprecations_spec.rb +51 -0
- data/spec/functional/image_magick_app_spec.rb +27 -0
- data/spec/functional/model_urls_spec.rb +85 -0
- data/spec/functional/remote_on_the_fly_spec.rb +51 -0
- data/spec/functional/to_response_spec.rb +31 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/argument_matchers.rb +19 -0
- data/spec/support/image_matchers.rb +47 -0
- data/spec/support/simple_matchers.rb +53 -0
- data/yard/handlers/configurable_attr_handler.rb +38 -0
- data/yard/setup.rb +15 -0
- data/yard/templates/default/fulldoc/html/css/common.css +107 -0
- data/yard/templates/default/layout/html/layout.erb +89 -0
- data/yard/templates/default/module/html/configuration_summary.erb +31 -0
- data/yard/templates/default/module/setup.rb +17 -0
- metadata +544 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Array do
|
|
4
|
+
|
|
5
|
+
describe "to_dragonfly_unique_s" do
|
|
6
|
+
it "should concatenate the to_s's of each of the elements" do
|
|
7
|
+
[:a, true, 2, 5.2, "hello"].to_dragonfly_unique_s.should == 'atrue25.2hello'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should nest arrays" do
|
|
11
|
+
[:a, [:b, :c], :d].to_dragonfly_unique_s.should == 'abcd'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should be empty if empty" do
|
|
15
|
+
[].to_dragonfly_unique_s.should == ''
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Hash do
|
|
4
|
+
|
|
5
|
+
describe "to_dragonfly_unique_s" do
|
|
6
|
+
it "should concatenate the to_s's of each of the elements, sorted alphabetically" do
|
|
7
|
+
{'z' => nil, :a => 4, false => 'ice', 5 => 6.2}.to_dragonfly_unique_s.should == '56.2a4falseicez'
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "should nest correctly" do
|
|
11
|
+
{:m => 1, :a => {:c => 2, :b => 3}, :z => 4}.to_dragonfly_unique_s.should == 'ab3c2m1z4'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "should be empty if empty" do
|
|
15
|
+
{}.to_dragonfly_unique_s.should == ''
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe String do
|
|
4
|
+
|
|
5
|
+
describe "to_method_name" do
|
|
6
|
+
if RUBY_VERSION =~ /^1.8/
|
|
7
|
+
it "should return a string" do
|
|
8
|
+
'hello'.to_method_name.should == 'hello'
|
|
9
|
+
end
|
|
10
|
+
else
|
|
11
|
+
it "should return a symbol" do
|
|
12
|
+
'hello'.to_method_name.should == :hello
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Symbol do
|
|
4
|
+
|
|
5
|
+
describe "to_method_name" do
|
|
6
|
+
if RUBY_VERSION =~ /^1.8/
|
|
7
|
+
it "should return a string" do
|
|
8
|
+
:hello.to_method_name.should == 'hello'
|
|
9
|
+
end
|
|
10
|
+
else
|
|
11
|
+
it "should return a symbol" do
|
|
12
|
+
:hello.to_method_name.should == :hello
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
require File.dirname(__FILE__) + '/shared_data_store_examples'
|
|
4
|
+
require 'net/http'
|
|
5
|
+
|
|
6
|
+
describe Dragonfly::DataStorage::CouchDataStore do
|
|
7
|
+
|
|
8
|
+
before(:each) do
|
|
9
|
+
WebMock.allow_net_connect!
|
|
10
|
+
@data_store = Dragonfly::DataStorage::CouchDataStore.new(
|
|
11
|
+
:host => "localhost",
|
|
12
|
+
:port => "5984",
|
|
13
|
+
:username => "",
|
|
14
|
+
:password => "",
|
|
15
|
+
:database => "dragonfly_test"
|
|
16
|
+
)
|
|
17
|
+
begin
|
|
18
|
+
@data_store.db.get('ping')
|
|
19
|
+
rescue Errno::ECONNREFUSED => e
|
|
20
|
+
pending "You need to start CouchDB on localhost:5984 to test the CouchDataStore"
|
|
21
|
+
rescue RestClient::ResourceNotFound
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it_should_behave_like 'data_store'
|
|
27
|
+
|
|
28
|
+
describe "destroy" do
|
|
29
|
+
before(:each) do
|
|
30
|
+
@temp_object = Dragonfly::TempObject.new('gollum')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should raise an error if the data doesn't exist on destroy" do
|
|
34
|
+
uid = @data_store.store(@temp_object)
|
|
35
|
+
@data_store.destroy(uid)
|
|
36
|
+
lambda{
|
|
37
|
+
@data_store.destroy(uid)
|
|
38
|
+
}.should raise_error(Dragonfly::DataStorage::DataNotFound)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe "serving from couchdb" do
|
|
43
|
+
|
|
44
|
+
def get_content(uid, name)
|
|
45
|
+
Net::HTTP.start('localhost', 5984) {|http|
|
|
46
|
+
http.get("/dragonfly_test/#{uid}/#{name}")
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
before(:each) do
|
|
51
|
+
@temp_object = Dragonfly::TempObject.new('testingyo')
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should use the fallback by default" do
|
|
55
|
+
uid = @data_store.store(@temp_object)
|
|
56
|
+
response = get_content(uid, 'file')
|
|
57
|
+
response.body.should == 'testingyo'
|
|
58
|
+
response['Content-Type'].should == 'application/octet-stream'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should allow setting on store with 'content_type'" do
|
|
62
|
+
uid = @data_store.store(@temp_object, :content_type => 'text/plain')
|
|
63
|
+
response = get_content(uid, 'file')
|
|
64
|
+
response.body.should == 'testingyo'
|
|
65
|
+
response['Content-Type'].should == 'text/plain'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "should allow setting on store with 'mime_type'" do
|
|
69
|
+
uid = @data_store.store(@temp_object, :mime_type => 'text/plain-yo')
|
|
70
|
+
response = get_content(uid, 'file')
|
|
71
|
+
response.body.should == 'testingyo'
|
|
72
|
+
response['Content-Type'].should == 'text/plain-yo'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require File.dirname(__FILE__) + '/shared_data_store_examples'
|
|
3
|
+
|
|
4
|
+
describe Dragonfly::DataStorage::FileDataStore do
|
|
5
|
+
|
|
6
|
+
def touch_file(filename)
|
|
7
|
+
FileUtils.mkdir_p(File.dirname(filename))
|
|
8
|
+
FileUtils.touch(filename)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
before(:each) do
|
|
12
|
+
@data_store = Dragonfly::DataStorage::FileDataStore.new
|
|
13
|
+
@data_store.root_path = '/var/tmp/dragonfly_test'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
after(:each) do
|
|
17
|
+
# Clean up created files
|
|
18
|
+
FileUtils.rm_rf("#{@data_store.root_path}")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it_should_behave_like 'data_store'
|
|
22
|
+
|
|
23
|
+
before(:each) do
|
|
24
|
+
@temp_object = Dragonfly::TempObject.new('goobydoo')
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "store" do
|
|
28
|
+
|
|
29
|
+
def it_should_write_to_file(storage_path, temp_object)
|
|
30
|
+
temp_object.should_receive(:to_file).with(storage_path).and_return(mock('file', :close => nil))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
before(:each) do
|
|
34
|
+
# Set 'now' to a date in the past
|
|
35
|
+
Time.stub!(:now).and_return Time.mktime(1984,"may",4,14,28,1)
|
|
36
|
+
@file_pattern_prefix_without_root = '1984/05/04/14_28_01_0_'
|
|
37
|
+
@file_pattern_prefix = "#{@data_store.root_path}/#{@file_pattern_prefix_without_root}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should store the file in a folder based on date, with default filename" do
|
|
41
|
+
it_should_write_to_file("#{@file_pattern_prefix}file", @temp_object)
|
|
42
|
+
@data_store.store(@temp_object)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "should use the temp_object original filename if it exists" do
|
|
46
|
+
@temp_object.should_receive(:original_filename).at_least(:once).and_return('hello.there')
|
|
47
|
+
it_should_write_to_file("#{@file_pattern_prefix}hello.there", @temp_object)
|
|
48
|
+
@data_store.store(@temp_object)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should use the meta name if it exists" do
|
|
52
|
+
it_should_write_to_file("#{@file_pattern_prefix}damp.squib", @temp_object)
|
|
53
|
+
@data_store.store(@temp_object, :meta => {:name => 'damp.squib'})
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should prefer the meta name to the original filename" do
|
|
57
|
+
@temp_object.stub!(:original_filename).and_return('hello.there')
|
|
58
|
+
it_should_write_to_file("#{@file_pattern_prefix}damp.squib", @temp_object)
|
|
59
|
+
@data_store.store(@temp_object, :meta => {:name => 'damp.squib'})
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should get rid of funny characters in the temp_object original filename" do
|
|
63
|
+
@temp_object.should_receive(:original_filename).at_least(:once).and_return('A Picture with many spaces in its name (at 20:00 pm).png')
|
|
64
|
+
it_should_write_to_file("#{@file_pattern_prefix}A_Picture_with_many_spaces_in_its_name_at_20_00_pm_.png", @temp_object)
|
|
65
|
+
@data_store.store(@temp_object)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
describe "when the filename already exists" do
|
|
69
|
+
|
|
70
|
+
it "should use a different filename" do
|
|
71
|
+
touch_file("#{@file_pattern_prefix}file")
|
|
72
|
+
@data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file").and_return("#{@file_pattern_prefix}file_2")
|
|
73
|
+
it_should_write_to_file("#{@file_pattern_prefix}file_2", @temp_object)
|
|
74
|
+
@data_store.store(@temp_object)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should use a different filename taking into account the name and ext" do
|
|
78
|
+
@temp_object.should_receive(:original_filename).at_least(:once).and_return('hello.png')
|
|
79
|
+
touch_file("#{@file_pattern_prefix}hello.png")
|
|
80
|
+
@data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}hello.png").and_return("#{@file_pattern_prefix}blah.png")
|
|
81
|
+
@data_store.store(@temp_object)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should keep trying until it finds a free filename" do
|
|
85
|
+
touch_file("#{@file_pattern_prefix}file")
|
|
86
|
+
touch_file("#{@file_pattern_prefix}file_2")
|
|
87
|
+
@data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file").and_return("#{@file_pattern_prefix}file_2")
|
|
88
|
+
@data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file_2").and_return("#{@file_pattern_prefix}file_3")
|
|
89
|
+
it_should_write_to_file("#{@file_pattern_prefix}file_3", @temp_object)
|
|
90
|
+
@data_store.store(@temp_object)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe "specifying the uid" do
|
|
94
|
+
it "should allow for specifying the path to use" do
|
|
95
|
+
it_should_write_to_file("#{@data_store.root_path}/hello/there/mate.png", @temp_object)
|
|
96
|
+
@data_store.store(@temp_object, :path => 'hello/there/mate.png')
|
|
97
|
+
end
|
|
98
|
+
it "should correctly disambiguate if the file exists" do
|
|
99
|
+
touch_file("#{@data_store.root_path}/hello/there/mate.png")
|
|
100
|
+
@data_store.should_receive(:disambiguate).with("#{@data_store.root_path}/hello/there/mate.png").and_return("#{@data_store.root_path}/hello/there/mate_2.png")
|
|
101
|
+
it_should_write_to_file("#{@data_store.root_path}/hello/there/mate_2.png", @temp_object)
|
|
102
|
+
@data_store.store(@temp_object, :path => 'hello/there/mate.png')
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
describe "return value" do
|
|
109
|
+
|
|
110
|
+
it "should return the filepath without the root of the stored file when a file name is not provided" do
|
|
111
|
+
@data_store.store(@temp_object).should == "#{@file_pattern_prefix_without_root}file"
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should return the filepath without the root of the stored file when a file name is provided" do
|
|
115
|
+
@temp_object.should_receive(:original_filename).at_least(:once).and_return('hello.you.png')
|
|
116
|
+
@data_store.store(@temp_object).should == "#{@file_pattern_prefix_without_root}hello.you.png"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
describe "disambiguate" do
|
|
124
|
+
it "should add a suffix" do
|
|
125
|
+
@data_store.disambiguate('/some/file').should =~ %r{^/some/file_\w+$}
|
|
126
|
+
end
|
|
127
|
+
it "should add a suffix to the basename" do
|
|
128
|
+
@data_store.disambiguate('/some/file.png').should =~ %r{^/some/file_\w+\.png$}
|
|
129
|
+
end
|
|
130
|
+
it "should be random(-ish)" do
|
|
131
|
+
@data_store.disambiguate('/some/file').should_not == @data_store.disambiguate('/some/file')
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
describe "errors" do
|
|
136
|
+
|
|
137
|
+
it "should raise an error if it can't create a directory" do
|
|
138
|
+
FileUtils.should_receive(:mkdir_p).and_raise(Errno::EACCES)
|
|
139
|
+
lambda{ @data_store.store(@temp_object) }.should raise_error(Dragonfly::DataStorage::UnableToStore)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "should raise an error if it can't create a file" do
|
|
143
|
+
@temp_object.should_receive(:to_file).and_raise(Errno::EACCES)
|
|
144
|
+
lambda{ @data_store.store(@temp_object) }.should raise_error(Dragonfly::DataStorage::UnableToStore)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
describe "retrieve" do
|
|
150
|
+
it "should return a pathname" do
|
|
151
|
+
uid = @data_store.store(@temp_object)
|
|
152
|
+
pathname, meta = @data_store.retrieve(uid)
|
|
153
|
+
pathname.should be_a(Pathname)
|
|
154
|
+
end
|
|
155
|
+
it "should be able to retrieve any file, stored or not (and without meta data)" do
|
|
156
|
+
FileUtils.mkdir_p("#{@data_store.root_path}/jelly_beans/are")
|
|
157
|
+
File.open("#{@data_store.root_path}/jelly_beans/are/good", 'w'){|f| f.write('hey dog') }
|
|
158
|
+
pathname, meta = @data_store.retrieve("jelly_beans/are/good")
|
|
159
|
+
pathname.read.should == 'hey dog'
|
|
160
|
+
meta.should == {}
|
|
161
|
+
end
|
|
162
|
+
it "should work even if meta is stored in old .extra file" do
|
|
163
|
+
uid = @data_store.store(@temp_object, :meta => {:dog => 'food'})
|
|
164
|
+
FileUtils.mv("#{@data_store.root_path}/#{uid}.meta", "#{@data_store.root_path}/#{uid}.extra")
|
|
165
|
+
pathname, meta = @data_store.retrieve(uid)
|
|
166
|
+
meta.should == {:dog => 'food'}
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
describe "destroying" do
|
|
171
|
+
|
|
172
|
+
it "should prune empty directories when destroying" do
|
|
173
|
+
uid = @data_store.store(@temp_object)
|
|
174
|
+
@data_store.destroy(uid)
|
|
175
|
+
@data_store.root_path.should be_an_empty_directory
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "should raise an error if the data doesn't exist on destroy" do
|
|
179
|
+
uid = @data_store.store(@temp_object)
|
|
180
|
+
@data_store.destroy(uid)
|
|
181
|
+
lambda{
|
|
182
|
+
@data_store.destroy(uid)
|
|
183
|
+
}.should raise_error(Dragonfly::DataStorage::DataNotFound)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "should also destroy old .extra files" do
|
|
187
|
+
uid = @data_store.store(@temp_object)
|
|
188
|
+
FileUtils.cp("#{@data_store.root_path}/#{uid}.meta", "#{@data_store.root_path}/#{uid}.extra")
|
|
189
|
+
@data_store.destroy(uid)
|
|
190
|
+
File.exist?("#{@data_store.root_path}/#{uid}").should be_false
|
|
191
|
+
File.exist?("#{@data_store.root_path}/#{uid}.meta").should be_false
|
|
192
|
+
File.exist?("#{@data_store.root_path}/#{uid}.extra").should be_false
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
describe "relative paths" do
|
|
198
|
+
let(:store) { Dragonfly::DataStorage::FileDataStore.new }
|
|
199
|
+
let(:relative_path) { "2011/02/11/picture.jpg" }
|
|
200
|
+
let(:absolute_path) { "#{root_path}#{relative_path}" }
|
|
201
|
+
let(:root_path) { "/path/to/file/" }
|
|
202
|
+
|
|
203
|
+
before do
|
|
204
|
+
store.root_path = root_path
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
subject { store.send :relative, absolute_path }
|
|
208
|
+
|
|
209
|
+
it { should == relative_path }
|
|
210
|
+
|
|
211
|
+
context "where root path contains spaces" do
|
|
212
|
+
let(:root_path) { "/path/to/file name/" }
|
|
213
|
+
it { should == relative_path }
|
|
214
|
+
end
|
|
215
|
+
context "where root path contains special chars" do
|
|
216
|
+
let(:root_path) { "/path/to/file name (Special backup directory)/" }
|
|
217
|
+
it { should == relative_path }
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
describe "turning meta off" do
|
|
222
|
+
before(:each) do
|
|
223
|
+
@data_store.store_meta = false
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "should not write a meta file" do
|
|
227
|
+
uid = @data_store.store(@temp_object, :meta => {:bitrate => '35', :name => 'danny.boy'})
|
|
228
|
+
path = File.join(@data_store.root_path, uid) + '.meta'
|
|
229
|
+
File.exist?(path).should be_false
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "should return an empty hash on retrieve" do
|
|
233
|
+
uid = @data_store.store(@temp_object, :meta => {:bitrate => '35', :name => 'danny.boy'})
|
|
234
|
+
obj, meta = @data_store.retrieve(uid)
|
|
235
|
+
meta.should == {}
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it "should still destroy the meta file if it exists" do
|
|
239
|
+
@data_store.store_meta = true
|
|
240
|
+
uid = @data_store.store(@temp_object)
|
|
241
|
+
@data_store.store_meta = false
|
|
242
|
+
@data_store.destroy(uid)
|
|
243
|
+
@data_store.root_path.should be_an_empty_directory
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should still destroy properly if meta is on but the meta file doesn't exist" do
|
|
247
|
+
uid = @data_store.store(@temp_object)
|
|
248
|
+
@data_store.store_meta = true
|
|
249
|
+
@data_store.destroy(uid)
|
|
250
|
+
@data_store.root_path.should be_an_empty_directory
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
describe "urls for serving directly" do
|
|
255
|
+
before(:each) do
|
|
256
|
+
@uid = 'some/path/to/file.png'
|
|
257
|
+
@data_store.root_path = '/var/tmp/eggs'
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
it "should raise an error if called without configuring" do
|
|
261
|
+
expect{
|
|
262
|
+
@data_store.url_for(@uid)
|
|
263
|
+
}.to raise_error(Dragonfly::Configurable::NotConfigured)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
it "should work as expected when the the server root is above the root path" do
|
|
267
|
+
@data_store.server_root = '/var/tmp'
|
|
268
|
+
@data_store.url_for(@uid).should == '/eggs/some/path/to/file.png'
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
it "should work as expected when the the server root is the root path" do
|
|
272
|
+
@data_store.server_root = '/var/tmp/eggs'
|
|
273
|
+
@data_store.url_for(@uid).should == '/some/path/to/file.png'
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
it "should work as expected when the the server root is below the root path" do
|
|
277
|
+
@data_store.server_root = '/var/tmp/eggs/some/path'
|
|
278
|
+
@data_store.url_for(@uid).should == '/to/file.png'
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
it "should raise an error when the server root doesn't coincide with the root path" do
|
|
282
|
+
@data_store.server_root = '/var/blimey/eggs'
|
|
283
|
+
expect{
|
|
284
|
+
@data_store.url_for(@uid)
|
|
285
|
+
}.to raise_error(Dragonfly::DataStorage::FileDataStore::UnableToFormUrl)
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
it "should raise an error when the server root doesn't coincide with the uid" do
|
|
289
|
+
@data_store.server_root = '/var/tmp/eggs/some/gooney'
|
|
290
|
+
expect{
|
|
291
|
+
@data_store.url_for(@uid)
|
|
292
|
+
}.to raise_error(Dragonfly::DataStorage::FileDataStore::UnableToFormUrl)
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
end
|