fog-dragonfly 0.8.1

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.
Files changed (155) hide show
  1. data/.specopts +2 -0
  2. data/.yardopts +23 -0
  3. data/Gemfile +23 -0
  4. data/Gemfile.rails.2.3.5 +14 -0
  5. data/History.md +266 -0
  6. data/LICENSE +20 -0
  7. data/README.md +88 -0
  8. data/Rakefile +92 -0
  9. data/VERSION +1 -0
  10. data/config.ru +13 -0
  11. data/docs.watchr +1 -0
  12. data/dragonfly.gemspec +293 -0
  13. data/extra_docs/Analysers.md +108 -0
  14. data/extra_docs/Caching.md +23 -0
  15. data/extra_docs/Configuration.md +138 -0
  16. data/extra_docs/DataStorage.md +136 -0
  17. data/extra_docs/Encoding.md +96 -0
  18. data/extra_docs/GeneralUsage.md +121 -0
  19. data/extra_docs/Generators.md +102 -0
  20. data/extra_docs/Heroku.md +50 -0
  21. data/extra_docs/Index.md +36 -0
  22. data/extra_docs/MimeTypes.md +40 -0
  23. data/extra_docs/Models.md +266 -0
  24. data/extra_docs/Mongo.md +45 -0
  25. data/extra_docs/Processing.md +130 -0
  26. data/extra_docs/Rack.md +52 -0
  27. data/extra_docs/Rails2.md +55 -0
  28. data/extra_docs/Rails3.md +62 -0
  29. data/extra_docs/Sinatra.md +25 -0
  30. data/extra_docs/URLs.md +169 -0
  31. data/features/3.0.3.feature +8 -0
  32. data/features/images.feature +47 -0
  33. data/features/no_processing.feature +14 -0
  34. data/features/rails_2.3.5.feature +7 -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 +39 -0
  38. data/features/support/env.rb +40 -0
  39. data/fixtures/files/app/models/album.rb +3 -0
  40. data/fixtures/files/app/views/albums/new.html.erb +4 -0
  41. data/fixtures/files/app/views/albums/show.html.erb +4 -0
  42. data/fixtures/files/config/initializers/dragonfly.rb +4 -0
  43. data/fixtures/files/features/manage_album_images.feature +12 -0
  44. data/fixtures/files/features/step_definitions/image_steps.rb +15 -0
  45. data/fixtures/files/features/support/paths.rb +15 -0
  46. data/fixtures/files/features/text_images.feature +7 -0
  47. data/fixtures/rails_2.3.5/template.rb +10 -0
  48. data/fixtures/rails_3.0.3/template.rb +20 -0
  49. data/irbrc.rb +17 -0
  50. data/lib/dragonfly.rb +45 -0
  51. data/lib/dragonfly/active_model_extensions.rb +13 -0
  52. data/lib/dragonfly/active_model_extensions/attachment.rb +169 -0
  53. data/lib/dragonfly/active_model_extensions/class_methods.rb +45 -0
  54. data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
  55. data/lib/dragonfly/active_model_extensions/validations.rb +37 -0
  56. data/lib/dragonfly/analyser.rb +59 -0
  57. data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
  58. data/lib/dragonfly/analysis/image_magick_analyser.rb +47 -0
  59. data/lib/dragonfly/analysis/r_magick_analyser.rb +63 -0
  60. data/lib/dragonfly/app.rb +182 -0
  61. data/lib/dragonfly/config/heroku.rb +19 -0
  62. data/lib/dragonfly/config/image_magick.rb +41 -0
  63. data/lib/dragonfly/config/r_magick.rb +46 -0
  64. data/lib/dragonfly/config/rails.rb +17 -0
  65. data/lib/dragonfly/configurable.rb +119 -0
  66. data/lib/dragonfly/core_ext/object.rb +8 -0
  67. data/lib/dragonfly/core_ext/string.rb +9 -0
  68. data/lib/dragonfly/core_ext/symbol.rb +9 -0
  69. data/lib/dragonfly/data_storage.rb +9 -0
  70. data/lib/dragonfly/data_storage/file_data_store.rb +114 -0
  71. data/lib/dragonfly/data_storage/mongo_data_store.rb +82 -0
  72. data/lib/dragonfly/data_storage/s3data_store.rb +115 -0
  73. data/lib/dragonfly/encoder.rb +13 -0
  74. data/lib/dragonfly/encoding/image_magick_encoder.rb +57 -0
  75. data/lib/dragonfly/encoding/r_magick_encoder.rb +61 -0
  76. data/lib/dragonfly/function_manager.rb +69 -0
  77. data/lib/dragonfly/generation/hash_with_css_style_keys.rb +23 -0
  78. data/lib/dragonfly/generation/image_magick_generator.rb +140 -0
  79. data/lib/dragonfly/generation/r_magick_generator.rb +155 -0
  80. data/lib/dragonfly/generator.rb +9 -0
  81. data/lib/dragonfly/image_magick_utils.rb +81 -0
  82. data/lib/dragonfly/job.rb +371 -0
  83. data/lib/dragonfly/job_builder.rb +39 -0
  84. data/lib/dragonfly/job_definitions.rb +26 -0
  85. data/lib/dragonfly/job_endpoint.rb +15 -0
  86. data/lib/dragonfly/loggable.rb +28 -0
  87. data/lib/dragonfly/middleware.rb +34 -0
  88. data/lib/dragonfly/processing/image_magick_processor.rb +99 -0
  89. data/lib/dragonfly/processing/r_magick_processor.rb +126 -0
  90. data/lib/dragonfly/processor.rb +9 -0
  91. data/lib/dragonfly/r_magick_utils.rb +48 -0
  92. data/lib/dragonfly/rails/images.rb +22 -0
  93. data/lib/dragonfly/response.rb +82 -0
  94. data/lib/dragonfly/routed_endpoint.rb +40 -0
  95. data/lib/dragonfly/serializer.rb +32 -0
  96. data/lib/dragonfly/simple_cache.rb +23 -0
  97. data/lib/dragonfly/simple_endpoint.rb +63 -0
  98. data/lib/dragonfly/temp_object.rb +220 -0
  99. data/samples/beach.png +0 -0
  100. data/samples/egg.png +0 -0
  101. data/samples/round.gif +0 -0
  102. data/samples/sample.docx +0 -0
  103. data/samples/taj.jpg +0 -0
  104. data/spec/argument_matchers.rb +19 -0
  105. data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
  106. data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
  107. data/spec/dragonfly/active_model_extensions/model_spec.rb +723 -0
  108. data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
  109. data/spec/dragonfly/analyser_spec.rb +123 -0
  110. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +57 -0
  111. data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +15 -0
  112. data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +27 -0
  113. data/spec/dragonfly/analysis/shared_analyser_spec.rb +51 -0
  114. data/spec/dragonfly/app_spec.rb +280 -0
  115. data/spec/dragonfly/config/r_magick_spec.rb +25 -0
  116. data/spec/dragonfly/configurable_spec.rb +220 -0
  117. data/spec/dragonfly/core_ext/string_spec.rb +17 -0
  118. data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
  119. data/spec/dragonfly/data_storage/data_store_spec.rb +76 -0
  120. data/spec/dragonfly/data_storage/file_data_store_spec.rb +169 -0
  121. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +38 -0
  122. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +94 -0
  123. data/spec/dragonfly/deprecation_spec.rb +20 -0
  124. data/spec/dragonfly/encoding/image_magick_encoder_spec.rb +41 -0
  125. data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +37 -0
  126. data/spec/dragonfly/function_manager_spec.rb +154 -0
  127. data/spec/dragonfly/generation/hash_with_css_style_keys_spec.rb +24 -0
  128. data/spec/dragonfly/generation/image_magick_generator_spec.rb +12 -0
  129. data/spec/dragonfly/generation/r_magick_generator_spec.rb +24 -0
  130. data/spec/dragonfly/generation/shared_generator_spec.rb +91 -0
  131. data/spec/dragonfly/image_magick_utils_spec.rb +16 -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 +120 -0
  135. data/spec/dragonfly/job_spec.rb +773 -0
  136. data/spec/dragonfly/loggable_spec.rb +80 -0
  137. data/spec/dragonfly/middleware_spec.rb +68 -0
  138. data/spec/dragonfly/processing/image_magick_processor_spec.rb +29 -0
  139. data/spec/dragonfly/processing/r_magick_processor_spec.rb +26 -0
  140. data/spec/dragonfly/processing/shared_processing_spec.rb +215 -0
  141. data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
  142. data/spec/dragonfly/serializer_spec.rb +61 -0
  143. data/spec/dragonfly/simple_cache_spec.rb +27 -0
  144. data/spec/dragonfly/simple_endpoint_spec.rb +89 -0
  145. data/spec/dragonfly/temp_object_spec.rb +352 -0
  146. data/spec/image_matchers.rb +47 -0
  147. data/spec/simple_matchers.rb +44 -0
  148. data/spec/spec_helper.rb +58 -0
  149. data/yard/handlers/configurable_attr_handler.rb +38 -0
  150. data/yard/setup.rb +15 -0
  151. data/yard/templates/default/fulldoc/html/css/common.css +107 -0
  152. data/yard/templates/default/layout/html/layout.erb +87 -0
  153. data/yard/templates/default/module/html/configuration_summary.erb +31 -0
  154. data/yard/templates/default/module/setup.rb +17 -0
  155. metadata +550 -0
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe Dragonfly::Config::RMagick do
4
+
5
+ before(:each) do
6
+ @app = test_app
7
+ end
8
+
9
+ it "should configure all to use the filesystem by default" do
10
+ @app.configure_with(Dragonfly::Config::RMagick)
11
+ @app.analyser.get_registered(Dragonfly::Analysis::RMagickAnalyser).use_filesystem.should be_true
12
+ @app.processor.get_registered(Dragonfly::Processing::RMagickProcessor).use_filesystem.should be_true
13
+ @app.encoder.get_registered(Dragonfly::Encoding::RMagickEncoder).use_filesystem.should be_true
14
+ @app.generator.get_registered(Dragonfly::Generation::RMagickGenerator).use_filesystem.should be_true
15
+ end
16
+
17
+ it "should configure all not to use the filesystem if requested" do
18
+ @app.configure_with(Dragonfly::Config::RMagick, :use_filesystem => false)
19
+ @app.analyser.get_registered(Dragonfly::Analysis::RMagickAnalyser).use_filesystem.should be_false
20
+ @app.processor.get_registered(Dragonfly::Processing::RMagickProcessor).use_filesystem.should be_false
21
+ @app.encoder.get_registered(Dragonfly::Encoding::RMagickEncoder).use_filesystem.should be_false
22
+ @app.generator.get_registered(Dragonfly::Generation::RMagickGenerator).use_filesystem.should be_false
23
+ end
24
+
25
+ end
@@ -0,0 +1,220 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Dragonfly::Configurable do
4
+
5
+ before(:each) do
6
+ class Car
7
+ include Dragonfly::Configurable
8
+ configurable_attr :colour
9
+ configurable_attr :top_speed, 216
10
+ def self.other_thing=(thing); end
11
+ end
12
+ @car = Car.new
13
+ end
14
+
15
+ describe "setup" do
16
+ it "should provide attr_readers for configurable attributes" do
17
+ @car.should respond_to(:colour)
18
+ end
19
+
20
+ it "should provide attr_writers for configurable attributes" do
21
+ @car.colour = 'verde'
22
+ @car.colour.should == 'verde'
23
+ end
24
+
25
+ it "should set default values for configurable attributes" do
26
+ @car.top_speed.should == 216
27
+ end
28
+
29
+ it "should set the default as nil if not specified" do
30
+ @car.colour.should be_nil
31
+ end
32
+
33
+ it "should allow specifying configurable attrs as strings" do
34
+ class Bike
35
+ include Dragonfly::Configurable
36
+ configurable_attr 'colour', 'rude'
37
+ end
38
+ Bike.new.colour.should == 'rude'
39
+ end
40
+ end
41
+
42
+ describe "configuring" do
43
+ it "should allow you to change values" do
44
+ @car.configure do |c|
45
+ c.colour = 'red'
46
+ end
47
+ @car.colour.should == 'red'
48
+ end
49
+
50
+ it "should not allow you to call other methods on the object via the configuration" do
51
+ lambda{
52
+ @car.configure do |c|
53
+ c.other_thing = 5
54
+ end
55
+ }.should raise_error(Dragonfly::Configurable::BadConfigAttribute)
56
+ end
57
+
58
+ it "should return itself" do
59
+ @car.configure{|c|}.should == @car
60
+ end
61
+ end
62
+
63
+ describe "getting configuration" do
64
+ it "should return the configuration as a hash" do
65
+ @car.configuration.should == {:colour => nil, :top_speed => 216}
66
+ end
67
+ it "should not allow you to change the configuration via the hash" do
68
+ @car.configuration[:top_speed] = 555
69
+ @car.top_speed.should == 216
70
+ end
71
+ end
72
+
73
+ describe "multiple objects" do
74
+ it "should return the default configuration" do
75
+ Car.default_configuration.should == {:colour => nil, :top_speed => 216}
76
+ end
77
+ it "should allow instances to be configured differently" do
78
+ car1 = Car.new
79
+ car1.configure{|c| c.colour = 'green'}
80
+ car2 = Car.new
81
+ car2.configure{|c| c.colour = 'yellow'}
82
+ car1.configuration.should == {:colour => 'green', :top_speed => 216}
83
+ car2.configuration.should == {:colour => 'yellow', :top_speed => 216}
84
+ end
85
+ end
86
+
87
+ describe "lazy attributes" do
88
+ before(:each) do
89
+ cow = @cow = mock('cow')
90
+ class Lazy; end
91
+ Lazy.class_eval do
92
+ include Dragonfly::Configurable
93
+ configurable_attr(:sound){ cow.moo }
94
+ end
95
+ @lazy = Lazy.new
96
+ end
97
+ it "should not call the block if the configurable attribute is set to something else" do
98
+ @cow.should_not_receive(:moo)
99
+ @lazy.configure{|c| c.sound = 'baa' }
100
+ @lazy.sound.should == 'baa'
101
+ end
102
+ it "should call the block if it's not been changed, once it's accessed" do
103
+ @cow.should_receive(:moo).and_return('mooo!')
104
+ @lazy.sound.should == 'mooo!'
105
+ end
106
+ it "should not call the block when accessed again" do
107
+ @cow.should_receive(:moo).exactly(:once).and_return('mooo!')
108
+ @lazy.sound.should == 'mooo!'
109
+ @lazy.sound.should == 'mooo!'
110
+ end
111
+ it "should not call an explicitly passed in proc" do
112
+ @lazy.configure{|c| c.sound = lambda{ @cow.fart }}
113
+ @lazy.sound.should be_a(Proc)
114
+ end
115
+ end
116
+
117
+ describe "using in the singleton class" do
118
+ it "should work" do
119
+ class OneOff
120
+ class << self
121
+ include Dragonfly::Configurable
122
+ configurable_attr :food, 'bread'
123
+ end
124
+ end
125
+ OneOff.food.should == 'bread'
126
+ end
127
+ end
128
+
129
+ describe "configuration method" do
130
+
131
+ before(:each) do
132
+ class ClassWithMethod
133
+ include Dragonfly::Configurable
134
+ def add_thing(thing)
135
+ 'poo'
136
+ end
137
+ def remove_thing(thing)
138
+ 'bum'
139
+ end
140
+ configuration_method :add_thing, :remove_thing
141
+ end
142
+ @thing = ClassWithMethod.new
143
+ end
144
+
145
+ it "should allow calling the method through 'configure'" do
146
+ @thing.configure do |c|
147
+ c.add_thing('duck')
148
+ c.remove_thing('dog')
149
+ end
150
+ end
151
+
152
+ end
153
+
154
+ describe "nested configurable objects" do
155
+
156
+ it "should allow configuring nested configurable objects" do
157
+
158
+ class NestedThing
159
+ include Dragonfly::Configurable
160
+ configurable_attr :age, 29
161
+ end
162
+
163
+ class Car
164
+ def nested_thing
165
+ @nested_thing ||= NestedThing.new
166
+ end
167
+ end
168
+
169
+ @car.configure do |c|
170
+ c.nested_thing.configure do |nt|
171
+ nt.age = 50
172
+ end
173
+ end
174
+
175
+ @car.nested_thing.age.should == 50
176
+
177
+ end
178
+
179
+ end
180
+
181
+ describe "configuring with a configurer" do
182
+ before(:each) do
183
+ @cool_configuration = Object.new
184
+ def @cool_configuration.apply_configuration(car, colour=nil)
185
+ car.configure do |c|
186
+ c.colour = (colour || 'vermelho')
187
+ end
188
+ end
189
+ end
190
+
191
+ it "should allow configuration by a configurer" do
192
+ @car.configure_with(@cool_configuration)
193
+ @car.colour.should == 'vermelho'
194
+ @car.top_speed.should == 216
195
+ end
196
+
197
+ it "should pass any args through to the configurer" do
198
+ @car.configure_with(@cool_configuration, 'preto')
199
+ @car.colour.should == 'preto'
200
+ end
201
+
202
+ it "should yield a block for any extra configuration" do
203
+ @car.configure_with(@cool_configuration) do |c|
204
+ c.colour = 'branco'
205
+ end
206
+ @car.colour.should == 'branco'
207
+ end
208
+
209
+ it "should return itself" do
210
+ @car.configure_with(@cool_configuration).should == @car
211
+ end
212
+
213
+ it "should ask the object which object to configure with if a symbol is given" do
214
+ @car.should_receive(:configurer_for).with(:cool).and_return(@cool_configuration)
215
+ @car.configure_with(:cool)
216
+ @car.colour.should == 'vermelho'
217
+ end
218
+ end
219
+
220
+ end
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/../../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 File.dirname(__FILE__) + '/../../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
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe "data_store", :shared => true do
4
+
5
+ # Using these shared spec requires you to set the inst var @data_store
6
+
7
+ before(:each) do
8
+ @temp_object = Dragonfly::TempObject.new('gollum')
9
+ end
10
+
11
+ describe "store" do
12
+ it "should return a unique identifier for each storage" do
13
+ temp_object2 = Dragonfly::TempObject.new('gollum')
14
+ @data_store.store(@temp_object).should_not == @data_store.store(temp_object2)
15
+ end
16
+ it "should return a unique identifier for each storage even when the first is deleted" do
17
+ uid1 = @data_store.store(@temp_object)
18
+ @data_store.destroy(uid1)
19
+ uid2 = @data_store.store(@temp_object)
20
+ uid1.should_not == uid2
21
+ end
22
+ it "should allow for passing in options as a second argument" do
23
+ @data_store.store(@temp_object, :some => :option)
24
+ end
25
+ end
26
+
27
+ describe "retrieve" do
28
+
29
+ describe "without extra info" do
30
+ before(:each) do
31
+ uid = @data_store.store(@temp_object)
32
+ @obj, @extra_info = @data_store.retrieve(uid)
33
+ end
34
+
35
+ it "should retrieve the stored data" do
36
+ Dragonfly::TempObject.new(@obj).data.should == @temp_object.data
37
+ end
38
+
39
+ it { @extra_info[:name].should be_nil }
40
+ it { @extra_info[:meta].should be_a(Hash) }
41
+ end
42
+
43
+ describe "when extra info is given" do
44
+ before(:each) do
45
+ temp_object = Dragonfly::TempObject.new('gollum',
46
+ :name => 'danny.boy',
47
+ :meta => {:bitrate => '35'}
48
+ )
49
+ @uid = @data_store.store(temp_object)
50
+ @obj, @extra_info = @data_store.retrieve(@uid)
51
+ end
52
+
53
+ it { @extra_info[:name].should == 'danny.boy' }
54
+ it { @extra_info[:meta].should include_hash(:bitrate => '35') }
55
+ end
56
+
57
+ it "should raise an exception if the data doesn't exist" do
58
+ lambda{
59
+ @data_store.retrieve('gooble/gubbub')
60
+ }.should raise_error(Dragonfly::DataStorage::DataNotFound)
61
+ end
62
+ end
63
+
64
+ describe "destroy" do
65
+
66
+ it "should destroy the stored data" do
67
+ uid = @data_store.store(@temp_object)
68
+ @data_store.destroy(uid)
69
+ lambda{
70
+ @data_store.retrieve(uid)
71
+ }.should raise_error(Dragonfly::DataStorage::DataNotFound)
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,169 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+ require File.dirname(__FILE__) + '/data_store_spec'
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 name if it exists" do
46
+ @temp_object.should_receive(:name).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 get rid of funny characters in the temp_object name" do
52
+ @temp_object.should_receive(:name).at_least(:once).and_return('A Picture with many spaces in its name (at 20:00 pm).png')
53
+ it_should_write_to_file("#{@file_pattern_prefix}A_Picture_with_many_spaces_in_its_name_at_20_00_pm_.png", @temp_object)
54
+ @data_store.store(@temp_object)
55
+ end
56
+
57
+ describe "when the filename already exists" do
58
+
59
+ it "should use a different filename" do
60
+ touch_file("#{@file_pattern_prefix}file")
61
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file").and_return("#{@file_pattern_prefix}file_2")
62
+ it_should_write_to_file("#{@file_pattern_prefix}file_2", @temp_object)
63
+ @data_store.store(@temp_object)
64
+ end
65
+
66
+ it "should use a different filename taking into account the name and ext" do
67
+ @temp_object.should_receive(:name).at_least(:once).and_return('hello.png')
68
+ touch_file("#{@file_pattern_prefix}hello.png")
69
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}hello.png").and_return("#{@file_pattern_prefix}blah.png")
70
+ @data_store.store(@temp_object)
71
+ end
72
+
73
+ it "should keep trying until it finds a free filename" do
74
+ touch_file("#{@file_pattern_prefix}file")
75
+ touch_file("#{@file_pattern_prefix}file_2")
76
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file").and_return("#{@file_pattern_prefix}file_2")
77
+ @data_store.should_receive(:disambiguate).with("#{@file_pattern_prefix}file_2").and_return("#{@file_pattern_prefix}file_3")
78
+ it_should_write_to_file("#{@file_pattern_prefix}file_3", @temp_object)
79
+ @data_store.store(@temp_object)
80
+ end
81
+
82
+ describe "specifying the uid" do
83
+ it "should allow for specifying the path to use" do
84
+ it_should_write_to_file("#{@data_store.root_path}/hello/there/mate.png", @temp_object)
85
+ @data_store.store(@temp_object, :path => 'hello/there/mate.png')
86
+ end
87
+ it "should correctly disambiguate if the file exists" do
88
+ touch_file("#{@data_store.root_path}/hello/there/mate.png")
89
+ @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")
90
+ it_should_write_to_file("#{@data_store.root_path}/hello/there/mate_2.png", @temp_object)
91
+ @data_store.store(@temp_object, :path => 'hello/there/mate.png')
92
+ end
93
+ end
94
+
95
+ end
96
+
97
+ describe "return value" do
98
+
99
+ it "should return the filepath without the root of the stored file when a file name is not provided" do
100
+ @data_store.store(@temp_object).should == "#{@file_pattern_prefix_without_root}file"
101
+ end
102
+
103
+ it "should return the filepath without the root of the stored file when a file name is provided" do
104
+ @temp_object.should_receive(:name).at_least(:once).and_return('hello.you.png')
105
+ @data_store.store(@temp_object).should == "#{@file_pattern_prefix_without_root}hello.you.png"
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
112
+ describe "disambiguate" do
113
+ it "should add a suffix" do
114
+ @data_store.disambiguate('/some/file').should =~ %r{^/some/file_\w+$}
115
+ end
116
+ it "should add a suffix to the basename" do
117
+ @data_store.disambiguate('/some/file.png').should =~ %r{^/some/file_\w+\.png$}
118
+ end
119
+ it "should be random(-ish)" do
120
+ @data_store.disambiguate('/some/file').should_not == @data_store.disambiguate('/some/file')
121
+ end
122
+ end
123
+
124
+ describe "errors" do
125
+
126
+ it "should raise an error if it can't create a directory" do
127
+ FileUtils.should_receive(:mkdir_p).and_raise(Errno::EACCES)
128
+ lambda{ @data_store.store(@temp_object) }.should raise_error(Dragonfly::DataStorage::UnableToStore)
129
+ end
130
+
131
+ it "should raise an error if it can't create a file" do
132
+ @temp_object.should_receive(:to_file).and_raise(Errno::EACCES)
133
+ lambda{ @data_store.store(@temp_object) }.should raise_error(Dragonfly::DataStorage::UnableToStore)
134
+ end
135
+
136
+ end
137
+
138
+ describe "retrieve" do
139
+ it "should return a closed file" do
140
+ uid = @data_store.store(@temp_object)
141
+ file, extra = @data_store.retrieve(uid)
142
+ file.should be_closed
143
+ end
144
+ it "should be able to retrieve any file, stored or not (and without extra data)" do
145
+ FileUtils.mkdir_p("#{@data_store.root_path}/jelly_beans/are")
146
+ File.open("#{@data_store.root_path}/jelly_beans/are/good", 'w'){|f| f.write('hey dog') }
147
+ file, meta = @data_store.retrieve("jelly_beans/are/good")
148
+ File.read(file.path).should == 'hey dog'
149
+ meta.should == {}
150
+ end
151
+ end
152
+
153
+ describe "destroying" do
154
+
155
+ it "should raise an error if the data doesn't exist" do
156
+ lambda{
157
+ @data_store.destroy('gooble/gubbub')
158
+ }.should raise_error(Dragonfly::DataStorage::DataNotFound)
159
+ end
160
+
161
+ it "should prune empty directories when destroying" do
162
+ uid = @data_store.store(@temp_object)
163
+ @data_store.destroy(uid)
164
+ @data_store.root_path.should be_an_empty_directory
165
+ end
166
+
167
+ end
168
+
169
+ end