oahu-dragonfly 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. data/.rspec +1 -0
  2. data/.yardopts +24 -0
  3. data/Gemfile +30 -0
  4. data/History.md +323 -0
  5. data/LICENSE +20 -0
  6. data/README.md +88 -0
  7. data/Rakefile +50 -0
  8. data/VERSION +1 -0
  9. data/config.ru +14 -0
  10. data/docs.watchr +1 -0
  11. data/dragonfly.gemspec +297 -0
  12. data/extra_docs/Analysers.md +66 -0
  13. data/extra_docs/Caching.md +23 -0
  14. data/extra_docs/Configuration.md +124 -0
  15. data/extra_docs/Couch.md +49 -0
  16. data/extra_docs/DataStorage.md +153 -0
  17. data/extra_docs/Encoding.md +67 -0
  18. data/extra_docs/GeneralUsage.md +121 -0
  19. data/extra_docs/Generators.md +60 -0
  20. data/extra_docs/Heroku.md +50 -0
  21. data/extra_docs/ImageMagick.md +125 -0
  22. data/extra_docs/Index.md +33 -0
  23. data/extra_docs/MimeTypes.md +40 -0
  24. data/extra_docs/Models.md +272 -0
  25. data/extra_docs/Mongo.md +45 -0
  26. data/extra_docs/Processing.md +77 -0
  27. data/extra_docs/Rack.md +52 -0
  28. data/extra_docs/Rails2.md +57 -0
  29. data/extra_docs/Rails3.md +62 -0
  30. data/extra_docs/Sinatra.md +25 -0
  31. data/extra_docs/URLs.md +169 -0
  32. data/features/images.feature +47 -0
  33. data/features/no_processing.feature +14 -0
  34. data/features/rails_3.0.5.feature +8 -0
  35. data/features/steps/common_steps.rb +8 -0
  36. data/features/steps/dragonfly_steps.rb +66 -0
  37. data/features/steps/rails_steps.rb +28 -0
  38. data/features/support/env.rb +13 -0
  39. data/features/support/setup.rb +32 -0
  40. data/fixtures/rails_3.0.5/files/app/models/album.rb +7 -0
  41. data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
  42. data/fixtures/rails_3.0.5/files/app/views/albums/show.html.erb +6 -0
  43. data/fixtures/rails_3.0.5/files/config/initializers/dragonfly.rb +4 -0
  44. data/fixtures/rails_3.0.5/files/features/manage_album_images.feature +38 -0
  45. data/fixtures/rails_3.0.5/files/features/step_definitions/helper_steps.rb +7 -0
  46. data/fixtures/rails_3.0.5/files/features/step_definitions/image_steps.rb +25 -0
  47. data/fixtures/rails_3.0.5/files/features/support/paths.rb +17 -0
  48. data/fixtures/rails_3.0.5/files/features/text_images.feature +7 -0
  49. data/fixtures/rails_3.0.5/template.rb +20 -0
  50. data/irbrc.rb +18 -0
  51. data/lib/dragonfly.rb +55 -0
  52. data/lib/dragonfly/active_model_extensions.rb +13 -0
  53. data/lib/dragonfly/active_model_extensions/attachment.rb +250 -0
  54. data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +148 -0
  55. data/lib/dragonfly/active_model_extensions/class_methods.rb +95 -0
  56. data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
  57. data/lib/dragonfly/active_model_extensions/validations.rb +41 -0
  58. data/lib/dragonfly/analyser.rb +58 -0
  59. data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
  60. data/lib/dragonfly/analysis/image_magick_analyser.rb +6 -0
  61. data/lib/dragonfly/app.rb +172 -0
  62. data/lib/dragonfly/config/heroku.rb +19 -0
  63. data/lib/dragonfly/config/image_magick.rb +6 -0
  64. data/lib/dragonfly/config/rails.rb +20 -0
  65. data/lib/dragonfly/configurable.rb +207 -0
  66. data/lib/dragonfly/core_ext/array.rb +7 -0
  67. data/lib/dragonfly/core_ext/hash.rb +7 -0
  68. data/lib/dragonfly/core_ext/object.rb +12 -0
  69. data/lib/dragonfly/core_ext/string.rb +9 -0
  70. data/lib/dragonfly/core_ext/symbol.rb +9 -0
  71. data/lib/dragonfly/data_storage.rb +9 -0
  72. data/lib/dragonfly/data_storage/couch_data_store.rb +64 -0
  73. data/lib/dragonfly/data_storage/file_data_store.rb +141 -0
  74. data/lib/dragonfly/data_storage/mongo_data_store.rb +86 -0
  75. data/lib/dragonfly/data_storage/s3data_store.rb +145 -0
  76. data/lib/dragonfly/encoder.rb +13 -0
  77. data/lib/dragonfly/encoding/image_magick_encoder.rb +6 -0
  78. data/lib/dragonfly/function_manager.rb +71 -0
  79. data/lib/dragonfly/generation/image_magick_generator.rb +6 -0
  80. data/lib/dragonfly/generator.rb +9 -0
  81. data/lib/dragonfly/hash_with_css_style_keys.rb +21 -0
  82. data/lib/dragonfly/image_magick/analyser.rb +51 -0
  83. data/lib/dragonfly/image_magick/config.rb +41 -0
  84. data/lib/dragonfly/image_magick/encoder.rb +57 -0
  85. data/lib/dragonfly/image_magick/generator.rb +145 -0
  86. data/lib/dragonfly/image_magick/processor.rb +99 -0
  87. data/lib/dragonfly/image_magick/utils.rb +72 -0
  88. data/lib/dragonfly/image_magick_utils.rb +4 -0
  89. data/lib/dragonfly/job.rb +451 -0
  90. data/lib/dragonfly/job_builder.rb +39 -0
  91. data/lib/dragonfly/job_definitions.rb +26 -0
  92. data/lib/dragonfly/job_endpoint.rb +15 -0
  93. data/lib/dragonfly/loggable.rb +28 -0
  94. data/lib/dragonfly/middleware.rb +20 -0
  95. data/lib/dragonfly/processing/image_magick_processor.rb +6 -0
  96. data/lib/dragonfly/processor.rb +9 -0
  97. data/lib/dragonfly/rails/images.rb +27 -0
  98. data/lib/dragonfly/response.rb +97 -0
  99. data/lib/dragonfly/routed_endpoint.rb +40 -0
  100. data/lib/dragonfly/serializer.rb +32 -0
  101. data/lib/dragonfly/server.rb +113 -0
  102. data/lib/dragonfly/simple_cache.rb +23 -0
  103. data/lib/dragonfly/temp_object.rb +175 -0
  104. data/lib/dragonfly/url_mapper.rb +78 -0
  105. data/samples/beach.png +0 -0
  106. data/samples/egg.png +0 -0
  107. data/samples/round.gif +0 -0
  108. data/samples/sample.docx +0 -0
  109. data/samples/taj.jpg +0 -0
  110. data/spec/dragonfly/active_model_extensions/model_spec.rb +1426 -0
  111. data/spec/dragonfly/active_model_extensions/spec_helper.rb +91 -0
  112. data/spec/dragonfly/analyser_spec.rb +123 -0
  113. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +48 -0
  114. data/spec/dragonfly/app_spec.rb +135 -0
  115. data/spec/dragonfly/configurable_spec.rb +461 -0
  116. data/spec/dragonfly/core_ext/array_spec.rb +19 -0
  117. data/spec/dragonfly/core_ext/hash_spec.rb +19 -0
  118. data/spec/dragonfly/core_ext/string_spec.rb +17 -0
  119. data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
  120. data/spec/dragonfly/data_storage/couch_data_store_spec.rb +76 -0
  121. data/spec/dragonfly/data_storage/file_data_store_spec.rb +296 -0
  122. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +57 -0
  123. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +258 -0
  124. data/spec/dragonfly/data_storage/shared_data_store_examples.rb +77 -0
  125. data/spec/dragonfly/function_manager_spec.rb +154 -0
  126. data/spec/dragonfly/hash_with_css_style_keys_spec.rb +24 -0
  127. data/spec/dragonfly/image_magick/analyser_spec.rb +64 -0
  128. data/spec/dragonfly/image_magick/encoder_spec.rb +41 -0
  129. data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
  130. data/spec/dragonfly/image_magick/processor_spec.rb +233 -0
  131. data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
  132. data/spec/dragonfly/job_builder_spec.rb +37 -0
  133. data/spec/dragonfly/job_definitions_spec.rb +35 -0
  134. data/spec/dragonfly/job_endpoint_spec.rb +173 -0
  135. data/spec/dragonfly/job_spec.rb +1046 -0
  136. data/spec/dragonfly/loggable_spec.rb +80 -0
  137. data/spec/dragonfly/middleware_spec.rb +47 -0
  138. data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
  139. data/spec/dragonfly/serializer_spec.rb +61 -0
  140. data/spec/dragonfly/server_spec.rb +278 -0
  141. data/spec/dragonfly/simple_cache_spec.rb +27 -0
  142. data/spec/dragonfly/temp_object_spec.rb +306 -0
  143. data/spec/dragonfly/url_mapper_spec.rb +126 -0
  144. data/spec/functional/deprecations_spec.rb +51 -0
  145. data/spec/functional/image_magick_app_spec.rb +27 -0
  146. data/spec/functional/model_urls_spec.rb +85 -0
  147. data/spec/functional/remote_on_the_fly_spec.rb +51 -0
  148. data/spec/functional/to_response_spec.rb +31 -0
  149. data/spec/spec_helper.rb +51 -0
  150. data/spec/support/argument_matchers.rb +19 -0
  151. data/spec/support/image_matchers.rb +47 -0
  152. data/spec/support/simple_matchers.rb +53 -0
  153. data/yard/handlers/configurable_attr_handler.rb +38 -0
  154. data/yard/setup.rb +15 -0
  155. data/yard/templates/default/fulldoc/html/css/common.css +107 -0
  156. data/yard/templates/default/layout/html/layout.erb +89 -0
  157. data/yard/templates/default/module/html/configuration_summary.erb +31 -0
  158. data/yard/templates/default/module/setup.rb +17 -0
  159. 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