dragonfly 0.9.15 → 1.0

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.

Files changed (203) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -8
  3. data/.travis.yml +11 -0
  4. data/Gemfile +1 -0
  5. data/History.md +52 -2
  6. data/LICENSE +1 -1
  7. data/README.md +38 -95
  8. data/dev/grid.jpg +0 -0
  9. data/dev/irbrc.rb +27 -0
  10. data/dev/rails_template.rb +38 -0
  11. data/dev/test.ru +56 -0
  12. data/dev/test_rails +19 -0
  13. data/dragonfly.gemspec +3 -21
  14. data/lib/dragonfly.rb +45 -44
  15. data/lib/dragonfly/app.rb +175 -96
  16. data/lib/dragonfly/configurable.rb +71 -170
  17. data/lib/dragonfly/content.rb +211 -0
  18. data/lib/dragonfly/core_ext/object.rb +1 -6
  19. data/lib/dragonfly/file_data_store.rb +197 -0
  20. data/lib/dragonfly/image_magick/analysers/image_properties.rb +23 -0
  21. data/lib/dragonfly/image_magick/generators/convert.rb +19 -0
  22. data/lib/dragonfly/image_magick/generators/plain.rb +26 -0
  23. data/lib/dragonfly/image_magick/generators/plasma.rb +25 -0
  24. data/lib/dragonfly/image_magick/generators/text.rb +127 -0
  25. data/lib/dragonfly/image_magick/plugin.rb +83 -0
  26. data/lib/dragonfly/image_magick/processors/convert.rb +29 -0
  27. data/lib/dragonfly/image_magick/processors/encode.rb +18 -0
  28. data/lib/dragonfly/image_magick/processors/thumb.rb +76 -0
  29. data/lib/dragonfly/job.rb +118 -134
  30. data/lib/dragonfly/job_endpoint.rb +2 -0
  31. data/lib/dragonfly/memory_data_store.rb +34 -0
  32. data/lib/dragonfly/middleware.rb +5 -3
  33. data/lib/dragonfly/{active_model_extensions.rb → model.rb} +5 -3
  34. data/lib/dragonfly/{active_model_extensions → model}/attachment.rb +40 -35
  35. data/lib/dragonfly/{active_model_extensions → model}/attachment_class_methods.rb +36 -40
  36. data/lib/dragonfly/model/class_methods.rb +109 -0
  37. data/lib/dragonfly/{active_model_extensions → model}/instance_methods.rb +2 -2
  38. data/lib/dragonfly/{active_model_extensions → model}/validations.rb +17 -12
  39. data/lib/dragonfly/railtie.rb +8 -6
  40. data/lib/dragonfly/register.rb +27 -0
  41. data/lib/dragonfly/response.rb +47 -52
  42. data/lib/dragonfly/routed_endpoint.rb +4 -0
  43. data/lib/dragonfly/serializer.rb +15 -5
  44. data/lib/dragonfly/server.rb +56 -29
  45. data/lib/dragonfly/shell.rb +12 -23
  46. data/lib/dragonfly/spec/data_store_examples.rb +64 -0
  47. data/lib/dragonfly/temp_object.rb +32 -47
  48. data/lib/dragonfly/url_attributes.rb +19 -22
  49. data/lib/dragonfly/url_mapper.rb +3 -0
  50. data/lib/dragonfly/utils.rb +12 -0
  51. data/lib/dragonfly/version.rb +1 -1
  52. data/lib/dragonfly/whitelist.rb +19 -0
  53. data/lib/rails/generators/dragonfly/USAGE +8 -0
  54. data/lib/rails/generators/dragonfly/dragonfly_generator.rb +24 -0
  55. data/lib/rails/generators/dragonfly/templates/initializer.rb.erb +27 -0
  56. data/samples/gif.gif +0 -0
  57. data/spec/dragonfly/app_spec.rb +270 -64
  58. data/spec/dragonfly/configurable_spec.rb +142 -418
  59. data/spec/dragonfly/content_spec.rb +353 -0
  60. data/spec/dragonfly/cookie_monster_spec.rb +2 -1
  61. data/spec/dragonfly/file_data_store_spec.rb +301 -0
  62. data/spec/dragonfly/image_magick/analysers/image_properties_spec.rb +20 -0
  63. data/spec/dragonfly/image_magick/generators/convert_spec.rb +19 -0
  64. data/spec/dragonfly/image_magick/generators/plain_spec.rb +50 -0
  65. data/spec/dragonfly/image_magick/generators/plasma_spec.rb +32 -0
  66. data/spec/dragonfly/image_magick/generators/text_spec.rb +77 -0
  67. data/spec/dragonfly/image_magick/plugin_spec.rb +131 -0
  68. data/spec/dragonfly/image_magick/processors/convert_spec.rb +56 -0
  69. data/spec/dragonfly/image_magick/processors/thumb_spec.rb +173 -0
  70. data/spec/dragonfly/job_endpoint_spec.rb +30 -73
  71. data/spec/dragonfly/job_spec.rb +280 -608
  72. data/spec/dragonfly/memory_data_store_spec.rb +20 -0
  73. data/spec/dragonfly/middleware_spec.rb +47 -27
  74. data/spec/dragonfly/{active_model_extensions → model}/model_spec.rb +331 -555
  75. data/spec/dragonfly/model/validations_spec.rb +196 -0
  76. data/spec/dragonfly/register_spec.rb +35 -0
  77. data/spec/dragonfly/routed_endpoint_spec.rb +6 -6
  78. data/spec/dragonfly/serializer_spec.rb +13 -15
  79. data/spec/dragonfly/server_spec.rb +122 -46
  80. data/spec/dragonfly/shell_spec.rb +43 -24
  81. data/spec/dragonfly/temp_object_spec.rb +69 -94
  82. data/spec/dragonfly/url_attributes_spec.rb +49 -0
  83. data/spec/dragonfly/utils_spec.rb +32 -0
  84. data/spec/dragonfly/whitelist_spec.rb +30 -0
  85. data/spec/dragonfly_spec.rb +43 -0
  86. data/spec/fixtures/deprecated_stored_content/eggs.bonus +1 -0
  87. data/spec/fixtures/deprecated_stored_content/eggs.bonus.meta +1 -0
  88. data/spec/functional/configuration_spec.rb +19 -0
  89. data/spec/functional/model_urls_spec.rb +43 -41
  90. data/spec/functional/remote_on_the_fly_spec.rb +14 -16
  91. data/spec/functional/shell_commands_spec.rb +24 -14
  92. data/spec/functional/to_response_spec.rb +10 -10
  93. data/spec/functional/urls_spec.rb +5 -3
  94. data/spec/spec_helper.rb +23 -28
  95. data/spec/support/argument_matchers.rb +7 -8
  96. data/spec/support/image_matchers.rb +14 -36
  97. data/spec/support/model_helpers.rb +97 -0
  98. data/spec/support/simple_matchers.rb +12 -0
  99. metadata +92 -393
  100. data/.yardopts +0 -29
  101. data/Rakefile +0 -36
  102. data/config.ru +0 -14
  103. data/docs.watchr +0 -1
  104. data/extra_docs/Analysers.md +0 -68
  105. data/extra_docs/Caching.md +0 -23
  106. data/extra_docs/Configuration.md +0 -149
  107. data/extra_docs/Couch.md +0 -49
  108. data/extra_docs/DataStorage.md +0 -226
  109. data/extra_docs/Encoding.md +0 -67
  110. data/extra_docs/ExampleUseCases.md +0 -116
  111. data/extra_docs/GeneralUsage.md +0 -105
  112. data/extra_docs/Generators.md +0 -68
  113. data/extra_docs/Heroku.md +0 -50
  114. data/extra_docs/ImageMagick.md +0 -136
  115. data/extra_docs/Index.md +0 -33
  116. data/extra_docs/MimeTypes.md +0 -40
  117. data/extra_docs/Models.md +0 -441
  118. data/extra_docs/Mongo.md +0 -42
  119. data/extra_docs/Processing.md +0 -77
  120. data/extra_docs/Rack.md +0 -52
  121. data/extra_docs/Rails2.md +0 -57
  122. data/extra_docs/Rails3.md +0 -56
  123. data/extra_docs/ServingRemotely.md +0 -104
  124. data/extra_docs/Sinatra.md +0 -25
  125. data/extra_docs/URLs.md +0 -203
  126. data/features/images.feature +0 -47
  127. data/features/no_processing.feature +0 -14
  128. data/features/rails.feature +0 -8
  129. data/features/steps/common_steps.rb +0 -8
  130. data/features/steps/dragonfly_steps.rb +0 -66
  131. data/features/steps/rails_steps.rb +0 -40
  132. data/features/support/env.rb +0 -13
  133. data/features/support/setup.rb +0 -41
  134. data/fixtures/rails/files/app/models/album.rb +0 -6
  135. data/fixtures/rails/files/app/views/albums/new.html.erb +0 -7
  136. data/fixtures/rails/files/app/views/albums/show.html.erb +0 -6
  137. data/fixtures/rails/files/config/initializers/dragonfly.rb +0 -4
  138. data/fixtures/rails/files/features/manage_album_images.feature +0 -38
  139. data/fixtures/rails/files/features/step_definitions/helper_steps.rb +0 -7
  140. data/fixtures/rails/files/features/step_definitions/image_steps.rb +0 -25
  141. data/fixtures/rails/files/features/step_definitions/web_steps.rb +0 -189
  142. data/fixtures/rails/files/features/support/paths.rb +0 -17
  143. data/fixtures/rails/files/features/text_images.feature +0 -7
  144. data/fixtures/rails/template.rb +0 -20
  145. data/irbrc.rb +0 -19
  146. data/lib/dragonfly/active_model_extensions/class_methods.rb +0 -98
  147. data/lib/dragonfly/analyser.rb +0 -58
  148. data/lib/dragonfly/analysis/file_command_analyser.rb +0 -33
  149. data/lib/dragonfly/analysis/image_magick_analyser.rb +0 -6
  150. data/lib/dragonfly/config/heroku.rb +0 -26
  151. data/lib/dragonfly/config/image_magick.rb +0 -6
  152. data/lib/dragonfly/config/rails.rb +0 -20
  153. data/lib/dragonfly/data_storage.rb +0 -11
  154. data/lib/dragonfly/data_storage/couch_data_store.rb +0 -83
  155. data/lib/dragonfly/data_storage/file_data_store.rb +0 -144
  156. data/lib/dragonfly/data_storage/mongo_data_store.rb +0 -96
  157. data/lib/dragonfly/data_storage/s3data_store.rb +0 -168
  158. data/lib/dragonfly/encoder.rb +0 -13
  159. data/lib/dragonfly/encoding/image_magick_encoder.rb +0 -6
  160. data/lib/dragonfly/function_manager.rb +0 -67
  161. data/lib/dragonfly/generation/image_magick_generator.rb +0 -6
  162. data/lib/dragonfly/generator.rb +0 -9
  163. data/lib/dragonfly/image_magick/analyser.rb +0 -53
  164. data/lib/dragonfly/image_magick/config.rb +0 -44
  165. data/lib/dragonfly/image_magick/encoder.rb +0 -57
  166. data/lib/dragonfly/image_magick/generator.rb +0 -147
  167. data/lib/dragonfly/image_magick/processor.rb +0 -114
  168. data/lib/dragonfly/image_magick/utils.rb +0 -46
  169. data/lib/dragonfly/image_magick_utils.rb +0 -4
  170. data/lib/dragonfly/job_builder.rb +0 -39
  171. data/lib/dragonfly/job_definitions.rb +0 -30
  172. data/lib/dragonfly/loggable.rb +0 -28
  173. data/lib/dragonfly/processing/image_magick_processor.rb +0 -6
  174. data/lib/dragonfly/processor.rb +0 -9
  175. data/lib/dragonfly/rails/images.rb +0 -32
  176. data/lib/dragonfly/simple_cache.rb +0 -23
  177. data/spec/dragonfly/active_model_extensions/spec_helper.rb +0 -95
  178. data/spec/dragonfly/analyser_spec.rb +0 -123
  179. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +0 -49
  180. data/spec/dragonfly/data_storage/couch_data_store_spec.rb +0 -84
  181. data/spec/dragonfly/data_storage/file_data_store_spec.rb +0 -308
  182. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +0 -81
  183. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +0 -277
  184. data/spec/dragonfly/data_storage/shared_data_store_examples.rb +0 -77
  185. data/spec/dragonfly/function_manager_spec.rb +0 -154
  186. data/spec/dragonfly/image_magick/analyser_spec.rb +0 -73
  187. data/spec/dragonfly/image_magick/encoder_spec.rb +0 -46
  188. data/spec/dragonfly/image_magick/generator_spec.rb +0 -178
  189. data/spec/dragonfly/image_magick/processor_spec.rb +0 -293
  190. data/spec/dragonfly/job_builder_spec.rb +0 -37
  191. data/spec/dragonfly/job_definitions_spec.rb +0 -57
  192. data/spec/dragonfly/loggable_spec.rb +0 -80
  193. data/spec/dragonfly/simple_cache_spec.rb +0 -27
  194. data/spec/dragonfly/url_attributes.rb +0 -47
  195. data/spec/functional/deprecations_spec.rb +0 -51
  196. data/spec/functional/image_magick_app_spec.rb +0 -27
  197. data/spec/test_imagemagick.ru +0 -49
  198. data/yard/handlers/configurable_attr_handler.rb +0 -38
  199. data/yard/setup.rb +0 -15
  200. data/yard/templates/default/fulldoc/html/css/common.css +0 -109
  201. data/yard/templates/default/layout/html/layout.erb +0 -93
  202. data/yard/templates/default/module/html/configuration_summary.erb +0 -31
  203. data/yard/templates/default/module/setup.rb +0 -17
Binary file
@@ -19,8 +19,12 @@ describe Dragonfly::App do
19
19
  Dragonfly::App.instance(:images).should == app
20
20
  end
21
21
 
22
- it "should also work using square brackets" do
23
- Dragonfly[:images].should == Dragonfly::App.instance(:images)
22
+ it "has a default instance" do
23
+ Dragonfly::App.instance.should be_a(Dragonfly::App)
24
+ end
25
+
26
+ it "returns the default instance if passed nil" do
27
+ Dragonfly::App.instance(nil).should == Dragonfly::App.instance
24
28
  end
25
29
 
26
30
  end
@@ -33,41 +37,97 @@ describe Dragonfly::App do
33
37
  end
34
38
  end
35
39
 
40
+ describe "destroy_apps" do
41
+ it "destroys the dragonfly apps" do
42
+ Dragonfly::App.instance(:gug)
43
+ Dragonfly::App.instance(:blug)
44
+ Dragonfly::App.apps.length.should == 2
45
+ Dragonfly::App.destroy_apps
46
+ Dragonfly::App.apps.length.should == 0
47
+ end
48
+ end
49
+
36
50
  describe "mime types" do
51
+ let(:app) { test_app }
52
+
37
53
  describe "#mime_type_for" do
38
- before(:each) do
39
- @app = test_app
40
- end
41
54
  it "should return the correct mime type for a symbol" do
42
- @app.mime_type_for(:png).should == 'image/png'
55
+ app.mime_type_for(:png).should == 'image/png'
43
56
  end
44
57
  it "should work for strings" do
45
- @app.mime_type_for('png').should == 'image/png'
58
+ app.mime_type_for('png').should == 'image/png'
46
59
  end
47
60
  it "should work with uppercase strings" do
48
- @app.mime_type_for('PNG').should == 'image/png'
61
+ app.mime_type_for('PNG').should == 'image/png'
49
62
  end
50
63
  it "should work with a dot" do
51
- @app.mime_type_for('.png').should == 'image/png'
64
+ app.mime_type_for('.png').should == 'image/png'
52
65
  end
53
- it "should return nil if not known" do
54
- @app.mime_type_for(:mark).should be_nil
66
+ it "should return the fallback if not known" do
67
+ app.mime_type_for(:mark).should == 'application/octet-stream'
55
68
  end
56
69
  it "should allow for configuring extra mime types" do
57
- @app.register_mime_type 'mark', 'application/mark'
58
- @app.mime_type_for(:mark).should == 'application/mark'
70
+ app.add_mime_type 'mark', 'application/mark'
71
+ app.mime_type_for(:mark).should == 'application/mark'
59
72
  end
60
73
  it "should override existing mime types when registered" do
61
- @app.register_mime_type :png, 'ping/pong'
62
- @app.mime_type_for(:png).should == 'ping/pong'
74
+ app.add_mime_type :png, 'ping/pong'
75
+ app.mime_type_for(:png).should == 'ping/pong'
63
76
  end
64
77
  it "should have a per-app mime-type configuration" do
65
- other_app = Dragonfly[:other_app]
66
- @app.register_mime_type(:mark, 'first/one')
67
- other_app.register_mime_type(:mark, 'second/one')
68
- @app.mime_type_for(:mark).should == 'first/one'
78
+ other_app = Dragonfly.app(:other_app)
79
+ app.add_mime_type(:mark, 'first/one')
80
+ other_app.add_mime_type(:mark, 'second/one')
81
+ app.mime_type_for(:mark).should == 'first/one'
69
82
  other_app.mime_type_for(:mark).should == 'second/one'
70
83
  end
84
+ it "can be added via configure" do
85
+ app.configure{ mime_type 'mark', 'application/mark' }
86
+ app.mime_type_for(:mark).should == 'application/mark'
87
+ end
88
+ end
89
+
90
+ describe "#ext_for" do
91
+ it "returns the ext corresponding to a mime_type" do
92
+ app.ext_for('image/png').should == 'png'
93
+ end
94
+
95
+ it "returns nil if non-existent" do
96
+ app.ext_for('big/bum').should be_nil
97
+ end
98
+
99
+ it "returns txt for text/plain" do
100
+ app.ext_for('text/plain').should == 'txt'
101
+ end
102
+ end
103
+ end
104
+
105
+ describe "create" do
106
+ let (:app) { test_app }
107
+
108
+ it "creates a new job with the specified data/meta" do
109
+ job = app.create("hello", 'a' => 'b')
110
+ job.should be_a(Dragonfly::Job)
111
+ job.data.should == 'hello'
112
+ job.meta['a'].should == 'b'
113
+ end
114
+
115
+ it "accepts other jobs" do
116
+ job2 = app.create("other", 'c' => 'd')
117
+ job = app.create(job2)
118
+ job.data.should == 'other'
119
+ job.meta['c'].should == 'd'
120
+ end
121
+
122
+ it "accepts Attachments" do
123
+ Car = new_model_class('Car', :make_uid) do
124
+ dragonfly_accessor :make
125
+ end
126
+ car = Car.new(:make => 'jaguar')
127
+ car.make.meta['a'] = 'b'
128
+ job = app.create(car.make)
129
+ job.data.should == 'jaguar'
130
+ job.meta['a'].should == 'b'
71
131
  end
72
132
  end
73
133
 
@@ -88,86 +148,232 @@ describe Dragonfly::App do
88
148
  end
89
149
 
90
150
  describe "#store" do
91
- before(:each) do
92
- @app = test_app
93
- end
151
+ let (:app) { test_app }
152
+
94
153
  it "should allow just storing content" do
95
- @app.datastore.should_receive(:store).with(a_temp_object_with_data("HELLO"), {})
96
- @app.store("HELLO")
97
- end
98
- it "should allow storing using a TempObject" do
99
- temp_object = Dragonfly::TempObject.new("HELLO")
100
- @app.datastore.should_receive(:store).with(temp_object, {})
101
- @app.store(temp_object)
102
- end
103
- it "should allow storing with extra stuff" do
104
- @app.datastore.should_receive(:store).with do |temp_object, opts|
105
- temp_object.data.should == 'HELLO'
106
- temp_object.meta.should == {:egg => :head}
107
- opts[:option].should == :blarney
154
+ app.datastore.should_receive(:write).with do |content, opts|
155
+ content.data.should == "HELLO"
108
156
  end
109
- @app.store("HELLO", :meta => {:egg => :head}, :option => :blarney)
157
+ app.store("HELLO")
110
158
  end
111
- it "should still pass in meta in the opts arg, for deprecated use of meta" do
112
- @app.datastore.should_receive(:store).with do |temp_object, opts|
113
- opts[:meta].should == {:egg => :head}
159
+
160
+ it "passes meta and options through too" do
161
+ app.datastore.should_receive(:write).with do |content, opts|
162
+ content.data.should == "HELLO"
163
+ content.meta.should == {'d' => 3}
164
+ opts.should == {:a => :b}
114
165
  end
115
- @app.store("HELLO", :meta => {:egg => :head}, :option => :blarney)
166
+ app.store("HELLO", {'d' => 3}, {:a => :b})
116
167
  end
117
168
  end
118
169
 
119
170
  describe "url_for" do
120
- before(:each) do
121
- @app = test_app
122
- @job = @app.fetch('eggs')
123
- end
171
+ let (:app) { test_app }
172
+ let (:job) { app.fetch('eggs') }
173
+
124
174
  it "should give the server url by default" do
125
- @app.url_for(@job).should =~ %r{^/\w+$}
175
+ app.url_for(job).should =~ %r{^/\w+$}
126
176
  end
127
177
  it "should allow configuring" do
128
- @app.configure do |c|
129
- c.define_url do |app, job, opts|
178
+ app.configure do
179
+ define_url do |app, job, opts|
130
180
  "doogies"
131
181
  end
132
182
  end
133
- @app.url_for(@job).should == 'doogies'
183
+ app.url_for(job).should == 'doogies'
134
184
  end
135
185
  it "should yield the correct dooberries" do
136
- @app.define_url do |app, job, opts|
186
+ app.define_url do |app, job, opts|
137
187
  [app, job, opts]
138
188
  end
139
- @app.url_for(@job, {'chuddies' => 'margate'}).should == [@app, @job, {'chuddies' => 'margate'}]
189
+ app.url_for(job, {'chuddies' => 'margate'}).should == [app, job, {'chuddies' => 'margate'}]
140
190
  end
141
191
  end
142
192
 
143
- describe "reflection methods" do
193
+ describe "adding generators" do
144
194
  before(:each) do
145
- @app = test_app.configure do |c|
146
- c.processor.add(:milk){}
147
- c.generator.add(:butter){}
148
- c.analyser.add(:cheese){}
149
- c.job(:bacon){}
195
+ @app = test_app.configure do
196
+ generator(:butter){ "BUTTER" }
150
197
  end
151
-
152
- end
153
- it "should return processor methods" do
154
- @app.processor_methods.should == [:milk]
155
198
  end
156
199
  it "should return generator methods" do
157
200
  @app.generator_methods.should == [:butter]
158
201
  end
202
+ end
203
+
204
+ describe "adding processors" do
205
+ before(:each) do
206
+ @app = test_app.configure do
207
+ processor(:double){}
208
+ end
209
+ end
210
+ it "should add a method" do
211
+ job1 = @app.create("bunga")
212
+ job2 = job1.double
213
+ job1.should_not == job2
214
+ job1.to_a.should == []
215
+ job2.to_a.should == [['p', :double]]
216
+ end
217
+ it "should add a bang method" do
218
+ job = @app.create("bunga")
219
+ job.double!.should == job
220
+ job.to_a.should == [['p', :double]]
221
+ end
222
+ it "should return processor methods" do
223
+ @app.processor_methods.should == [:double]
224
+ end
225
+ end
226
+
227
+ describe "adding analysers" do
228
+ before(:each) do
229
+ @app = test_app.configure do
230
+ analyser(:length){|content| content.size }
231
+ end
232
+ end
233
+ it "should add a method" do
234
+ @app.create('123').length.should == 3
235
+ end
159
236
  it "should return analyser methods" do
160
- @app.analyser_methods.should == [:cheese]
237
+ @app.analyser_methods.should == [:length]
161
238
  end
162
- it "should return job methods" do
163
- @app.job_methods.should == [:bacon]
239
+ end
240
+
241
+ describe "response headers" do
242
+ let (:app) {test_app}
243
+
244
+ it "adds a response header" do
245
+ app.response_header 'Cache-Control', "private"
246
+ app.response_headers["Cache-Control"].should == 'private'
247
+ end
248
+
249
+ it "adds a response header using a block" do
250
+ app.response_header 'Cache-Control' do "private" end
251
+ app.response_headers["Cache-Control"].should be_a(Proc)
252
+ end
253
+
254
+ it "allows calling through the config" do
255
+ app.configure{ response_header 'Cache-Control', "private" }
164
256
  end
165
257
  end
166
258
 
167
259
  describe "inspect" do
168
260
  it "should give a neat output" do
169
- Dragonfly[:hello].inspect.should == "<Dragonfly::App name=:hello >"
261
+ Dragonfly.app(:hello).inspect.should == "<Dragonfly::App name=:hello >"
262
+ end
263
+ end
264
+
265
+ describe "configuration" do
266
+
267
+ let(:app){ test_app }
268
+
269
+ describe "datastore" do
270
+ it "sets the datastore" do
271
+ store = double('datastore')
272
+ app.configure{ datastore store }
273
+ app.datastore.should == store
274
+ end
275
+
276
+ {
277
+ :file => Dragonfly::FileDataStore,
278
+ :memory => Dragonfly::MemoryDataStore
279
+ }.each do |symbol, klass|
280
+ it "recognises the #{symbol.inspect} shortcut for S3DataStore" do
281
+ app.configure{ datastore symbol }
282
+ app.datastore.should be_a(klass)
283
+ end
284
+ end
285
+ end
286
+
287
+ it "raises an error if it doesn't know the symbol" do
288
+ expect{
289
+ app.configure{ datastore :hello }
290
+ }.to raise_error(Dragonfly::App::UnregisteredDataStore)
291
+ end
292
+
293
+ it "passes args through to the initializer if a symbol is given" do
294
+ app.configure{ datastore :file, :root_path => '/some/path' }
295
+ app.datastore.root_path.should == '/some/path'
296
+ end
297
+
298
+ it "complains if extra args are given but first is not a symbol" do
299
+ store = double('datastore')
300
+ expect{
301
+ app.configure{ datastore store, :some => 'args' }
302
+ }.to raise_error(ArgumentError)
303
+ end
304
+
305
+ end
306
+
307
+ describe "define" do
308
+ let(:app){ test_app }
309
+
310
+ before :each do
311
+ app.define :exclaim do |n|
312
+ data.upcase + "!"*n
313
+ end
314
+ end
315
+
316
+ it "allows defining methods on jobs" do
317
+ app.create("snowman").exclaim(3).should == 'SNOWMAN!!!'
318
+ end
319
+
320
+ it "can be added through configure" do
321
+ app.configure{ define(:googie){} }
322
+ app.create("snowman").googie.should be_nil
323
+ end
324
+ end
325
+
326
+ describe "shell" do
327
+ let(:app){ test_app }
328
+
329
+ it "has a shell" do
330
+ app.shell.should be_a(Dragonfly::Shell)
331
+ end
332
+ end
333
+
334
+ describe "env" do
335
+ let(:app){ test_app }
336
+
337
+ it "stores environment variables" do
338
+ app.env.should == {}
339
+ app.env[:doogie] = 'blisto'
340
+ app.env[:doogie].should == 'blisto'
341
+ end
342
+ end
343
+
344
+ describe "deprecations" do
345
+ it "raises a message when using App#[]" do
346
+ expect {
347
+ Dragonfly::App[:images]
348
+ }.to raise_error(/Dragonfly::App\[:images\] .* Dragonfly\.app /)
349
+ end
350
+
351
+ it "raises a message when configuring with an old datastore" do
352
+ expect {
353
+ Dragonfly.app.use_datastore(double("datastore", :store => "asdf", :retrieve => "ASDF", :destroy => nil))
354
+ }.to raise_error(/read/)
355
+ end
356
+
357
+ it "raises a messages when configuring with a bad parameter" do
358
+ expect {
359
+ Dragonfly.app.configure do |c|
360
+ c.url_format = '/media/:job'
361
+ end
362
+ }.to raise_error(/no method.*changed.*docs/)
363
+ end
364
+
365
+ it "raises a message when calling App#define_macro" do
366
+ expect {
367
+ Dragonfly.app.define_macro(Object, :image_accessor)
368
+ }.to raise_error(/dragonfly_accessor/)
369
+ end
370
+
371
+ it "raises a message when calling App#define_macro_on_include" do
372
+ expect {
373
+ Dragonfly.app.define_macro_on_include(Module.new, :image_accessor)
374
+ }.to raise_error(/dragonfly_accessor/)
170
375
  end
171
376
  end
172
377
 
173
378
  end
379
+
@@ -2,478 +2,202 @@ require 'spec_helper'
2
2
 
3
3
  describe Dragonfly::Configurable do
4
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
5
+ describe "Configurer" do
19
6
 
20
- it "should provide attr_writers for configurable attributes" do
21
- @car.colour = 'verde'
22
- @car.colour.should == 'verde'
23
- end
7
+ let (:configurer) { Dragonfly::Configurable::Configurer.new do
8
+ def colour(colour)
9
+ obj.colour = colour
10
+ end
11
+ end }
24
12
 
25
- it "should set default values for configurable attributes" do
26
- @car.top_speed.should == 216
27
- end
13
+ let (:obj) { Object.new }
28
14
 
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 setting to nil" do
34
- @car.top_speed = nil
35
- @car.top_speed.should be_nil
36
- end
37
-
38
- it "should allow specifying configurable attrs as strings" do
39
- class Bike
40
- include Dragonfly::Configurable
41
- configurable_attr 'colour', 'rude'
15
+ it "allows configuring" do
16
+ obj.should_receive(:colour=).with('red')
17
+ configurer.configure(obj) do
18
+ colour 'red'
42
19
  end
43
- Bike.new.colour.should == 'rude'
44
20
  end
45
- end
46
21
 
47
- describe "configuring" do
48
- it "should allow you to change values" do
49
- @car.configure do |c|
50
- c.colour = 'red'
51
- end
52
- @car.colour.should == 'red'
53
- end
54
-
55
- it "should not allow you to call other methods on the object via the configuration" do
56
- lambda{
57
- @car.configure do |c|
58
- c.other_thing = 5
59
- end
60
- }.should raise_error(Dragonfly::Configurable::BadConfigAttribute)
61
- end
62
-
63
- it "should return itself" do
64
- @car.configure{|c|}.should == @car
65
- end
66
- end
67
-
68
- describe "getting configuration" do
69
- it "should return the configuration when nothing is set" do
70
- @car.configuration.should == {}
71
- end
72
- it "should return the configuration when something is set" do
73
- @car.top_speed = 10
74
- @car.configuration.should == {:top_speed => 10}
75
- end
76
- end
77
-
78
- describe "multiple objects" do
79
- it "should return the default configuration" do
80
- Car.default_configuration.should == {:colour => nil, :top_speed => 216}
81
- end
82
- it "should allow instances to be configured differently" do
83
- car1 = Car.new
84
- car1.configure{|c| c.colour = 'green'}
85
- car2 = Car.new
86
- car2.configure{|c| c.colour = 'yellow'}
87
- car1.configuration.should == {:colour => 'green'}
88
- car2.configuration.should == {:colour => 'yellow'}
89
- end
90
- end
91
-
92
- describe "lazy attributes" do
93
- before(:each) do
94
- cow = @cow = mock('cow')
95
- class Lazy; end
96
- Lazy.class_eval do
97
- include Dragonfly::Configurable
98
- configurable_attr(:sound){ cow.moo }
99
- end
100
- @lazy = Lazy.new
101
- end
102
- it "should not call the block if the configurable attribute is set to something else" do
103
- @cow.should_not_receive(:moo)
104
- @lazy.configure{|c| c.sound = 'baa' }
105
- @lazy.sound.should == 'baa'
106
- end
107
- it "should call the block if it's not been changed, once it's accessed" do
108
- @cow.should_receive(:moo).and_return('mooo!')
109
- @lazy.sound.should == 'mooo!'
110
- end
111
- it "should not call the block when accessed again" do
112
- @cow.should_receive(:moo).exactly(:once).and_return('mooo!')
113
- @lazy.sound.should == 'mooo!'
114
- @lazy.sound.should == 'mooo!'
115
- end
116
- it "should not call an explicitly passed in proc" do
117
- @lazy.configure{|c| c.sound = lambda{ @cow.fart }}
118
- @lazy.sound.should be_a(Proc)
119
- end
120
- end
121
-
122
- describe "configuration method" do
123
-
124
- before(:each) do
125
- class ClassWithMethod
126
- include Dragonfly::Configurable
127
- def add_thing(thing)
128
- 'poo'
129
- end
130
- def remove_thing(thing)
131
- 'bum'
22
+ it "doesn't allow non-existent methods" do
23
+ expect{
24
+ configurer.configure(obj) do
25
+ color 'red'
132
26
  end
133
- configuration_method :add_thing, :remove_thing
134
- end
135
- @thing = ClassWithMethod.new
136
- end
137
-
138
- it "should allow calling the method through 'configure'" do
139
- @thing.configure do |c|
140
- c.add_thing('duck')
141
- c.remove_thing('dog')
142
- end
27
+ }.to raise_error(NoMethodError)
143
28
  end
144
-
145
- end
146
-
147
- describe "nested configurable objects" do
148
29
 
149
- before(:each) do
150
- class NestedThing
151
- include Dragonfly::Configurable
152
- configurable_attr :age, 29
153
- def some_method(val)
154
- @some_thing = val
30
+ it "doesn't call non-existent methods on the object" do
31
+ obj.should_not_receive(:color=)
32
+ begin
33
+ configurer.configure(obj) do
34
+ color 'red'
155
35
  end
156
- configuration_method :some_method
157
- attr_reader :some_thing
36
+ rescue NoMethodError
158
37
  end
38
+ end
159
39
 
160
- class Car
161
- def nested_thing
162
- @nested_thing ||= NestedThing.new
163
- end
164
- nested_configurable :nested_thing
40
+ it "provides a 'writer' shortcut" do
41
+ configurer = Dragonfly::Configurable::Configurer.new do
42
+ writer :colour, :size
165
43
  end
166
-
167
- @car.configure do |c|
168
- c.nested_thing.configure do |nt|
169
- nt.age = 50
170
- nt.some_method('yo')
171
- end
44
+ obj.should_receive(:colour=).with('blue')
45
+ obj.should_receive(:size=).with('big')
46
+ configurer.configure(obj) do
47
+ colour 'blue'
48
+ size 'big'
172
49
  end
173
50
  end
174
51
 
175
- it "should allow configuring nested configurable accessors" do
176
- @car.nested_thing.age.should == 50
177
- end
178
-
179
- it "should allow configuring nested configurable normal methods" do
180
- @car.nested_thing.some_thing.should == 'yo'
181
- end
182
-
183
- it "should not allow configuring directly on the config object" do
184
- expect{
185
- @car.configure do |c|
186
- c.some_method('other')
187
- end
188
- }.to raise_error(Dragonfly::Configurable::BadConfigAttribute)
189
- end
190
- end
191
-
192
- describe "configuring with a saved config" do
193
- before(:each) do
194
- @cool_configuration = Object.new
195
- def @cool_configuration.apply_configuration(car, colour=nil)
196
- car.configure do |c|
197
- c.colour = (colour || 'vermelho')
198
- end
52
+ it "allows using the writer on another object" do
53
+ configurer = Dragonfly::Configurable::Configurer.new do
54
+ writer :colour, :for => :egg
199
55
  end
200
- end
201
-
202
- it "should allow configuration by a saved config" do
203
- @car.configure_with(@cool_configuration)
204
- @car.colour.should == 'vermelho'
205
- @car.top_speed.should == 216
206
- end
207
-
208
- it "should pass any args through to the saved config" do
209
- @car.configure_with(@cool_configuration, 'preto')
210
- @car.colour.should == 'preto'
211
- end
212
-
213
- it "should yield a block for any extra configuration" do
214
- @car.configure_with(@cool_configuration) do |c|
215
- c.colour = 'branco'
56
+ egg = double('egg')
57
+ obj.should_receive(:egg).and_return(egg)
58
+ egg.should_receive(:colour=).with('pink')
59
+ configurer.configure(obj) do
60
+ colour 'pink'
216
61
  end
217
- @car.colour.should == 'branco'
218
- end
219
-
220
- it "should return itself" do
221
- @car.configure_with(@cool_configuration).should == @car
222
62
  end
223
-
224
- describe "using a symbol to specify the config" do
225
63
 
226
- before(:all) do
227
- @rally_config = Object.new
228
- Car.register_configuration(:rally, @rally_config)
229
- @long_journey_config = Object.new
230
- Car.register_configuration(:long_journey){ @long_journey_config }
231
- Car.register_configuration(:some_library){ SomeLibrary }
64
+ it "provides a 'meth' shortcut" do
65
+ configurer = Dragonfly::Configurable::Configurer.new do
66
+ meth :jobby, :nobby
232
67
  end
233
-
234
- it "should map the symbol to the correct configuration" do
235
- @rally_config.should_receive(:apply_configuration).with(@car)
236
- @car.configure_with(:rally)
237
- end
238
-
239
- it "should map the symbol to the correct configuration lazily" do
240
- @long_journey_config.should_receive(:apply_configuration).with(@car)
241
- @car.configure_with(:long_journey)
68
+ obj.should_receive(:jobby).with('beans', :make => 5)
69
+ obj.should_receive(:nobby).with(['nuts'])
70
+ configurer.configure(obj) do
71
+ jobby 'beans', :make => 5
72
+ nobby ['nuts']
242
73
  end
74
+ end
243
75
 
244
- it "should throw an error if an unknown symbol is passed in" do
245
- lambda {
246
- @car.configure_with(:eggs)
247
- }.should raise_error(ArgumentError)
76
+ it "allows using 'meth' on another object" do
77
+ configurer = Dragonfly::Configurable::Configurer.new do
78
+ meth :jobby, :for => :egg
248
79
  end
249
-
250
- it "should only try to load the library when asked to" do
251
- lambda{
252
- @car.configure_with(:some_library)
253
- }.should raise_error(NameError, /uninitialized constant.*SomeLibrary/)
80
+ egg = double('egg')
81
+ obj.should_receive(:egg).and_return(egg)
82
+ egg.should_receive(:jobby).with('beans', :make => 5)
83
+ configurer.configure(obj) do
84
+ jobby 'beans', :make => 5
254
85
  end
255
86
  end
256
-
257
87
  end
258
-
259
- describe "falling back to another config" do
260
- before(:each) do
261
- class Garage
262
- include Dragonfly::Configurable
263
- configurable_attr :top_speed, 100
264
- end
265
- @garage = Garage.new
266
- @car.use_as_fallback_config(@garage)
267
- end
268
-
269
- describe "when nothing set" do
270
- it "should use its default" do
271
- @car.top_speed.should == 216
272
- end
273
- it "shouldn't affect the fallback config object" do
274
- @garage.top_speed.should == 100
275
- end
276
- end
277
-
278
- describe "if set" do
279
- before(:each) do
280
- @car.top_speed = 444
281
- end
282
- it "should work normally" do
283
- @car.top_speed.should == 444
284
- end
285
- it "shouldn't affect the fallback config object" do
286
- @garage.top_speed.should == 100
88
+
89
+ describe "plugins" do
90
+
91
+ let (:configurer) { Dragonfly::Configurable::Configurer.new{} }
92
+ let (:obj) { Object.new }
93
+
94
+ it "provides 'plugin' for using plugins" do
95
+ pluggy = double('plugin')
96
+ pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
97
+ configurer.configure(obj) do
98
+ plugin pluggy, :a, 'few' => ['args']
287
99
  end
288
100
  end
289
-
290
- describe "both set" do
291
- before(:each) do
292
- @car.top_speed = 444
293
- @garage.top_speed = 3000
294
- end
295
- it "should prefer its own setting" do
296
- @car.top_speed.should == 444
297
- end
298
- it "shouldn't affect the fallback config object" do
299
- @garage.top_speed.should == 3000
101
+
102
+ it "allows using 'plugin' with symbols" do
103
+ pluggy = double('plugin')
104
+ pluggy.should_receive(:call).with(obj, :a, 'few' => ['args'])
105
+ configurer.register_plugin(:pluggy){ pluggy }
106
+ configurer.configure(obj) do
107
+ plugin :pluggy, :a, 'few' => ['args']
300
108
  end
301
109
  end
302
-
303
- describe "the fallback config is set" do
304
- before(:each) do
305
- @garage.top_speed = 3000
306
- end
307
- it "should use the fallback config" do
308
- @car.top_speed.should == 3000
309
- end
310
- it "shouldn't affect the fallback config object" do
311
- @garage.top_speed.should == 3000
110
+
111
+ it "adds the plugin to the object's 'plugins' if it responds to it when using symbols" do
112
+ def obj.plugins; @plugins ||= {}; end
113
+ pluggy = proc{}
114
+ configurer.register_plugin(:pluggy){ pluggy }
115
+ configurer.configure(obj) do
116
+ plugin :pluggy
312
117
  end
118
+ obj.plugins[:pluggy].should == pluggy
313
119
  end
314
-
315
- describe "falling back multiple levels" do
316
- before(:each) do
317
- @klass = Class.new
318
- @klass.class_eval do
319
- include Dragonfly::Configurable
320
- configurable_attr :veg, 'carrot'
120
+
121
+ it "raises an error when a wrong symbol is used" do
122
+ expect{
123
+ configurer.configure(obj) do
124
+ plugin :pluggy, :a, 'few' => ['args']
321
125
  end
322
- @a = @klass.new
323
- @b = @klass.new
324
- @b.use_as_fallback_config(@a)
325
- @c = @klass.new
326
- @c.use_as_fallback_config(@b)
327
- end
328
-
329
- it "should be the default if nothing set" do
330
- @c.veg.should == 'carrot'
331
- end
332
-
333
- it "should fall all the way back to the top one if necessary" do
334
- @a.veg = 'turnip'
335
- @c.veg.should == 'turnip'
336
- end
337
-
338
- it "should prefer the closer one over the further away one" do
339
- @b.veg = 'tatty'
340
- @a.veg = 'turnip'
341
- @c.veg.should == 'tatty'
342
- end
343
-
344
- it "should work properly with nils" do
345
- @a.veg = nil
346
- @c.veg = 'broc'
347
- @a.veg.should be_nil
348
- @b.veg.should be_nil
349
- @c.veg.should == 'broc'
350
- end
126
+ }.to raise_error(Dragonfly::Configurable::UnregisteredPlugin)
351
127
  end
352
-
353
- describe "objects with different methods" do
354
- before(:each) do
355
- class Dad
356
- include Dragonfly::Configurable
357
- end
358
- @dad = Dad.new
359
- class Kid
360
- include Dragonfly::Configurable
361
- configurable_attr :lug, 'default-lug'
362
- end
363
- @kid = Kid.new
364
- @kid.use_as_fallback_config(@dad)
365
- end
366
128
 
367
- it "should not allow setting on the fallback obj directly" do
368
- lambda{
369
- @dad.lug = 'leg'
370
- }.should raise_error(NoMethodError)
371
- end
129
+ end
372
130
 
373
- it "should not have the fallback obj respond to the method" do
374
- @dad.should_not respond_to(:lug=)
375
- end
131
+ describe "extending with Configurable" do
376
132
 
377
- it "should allow configuring through the fallback object even if it doesn't have that method" do
378
- @dad.configure do |c|
379
- c.lug = 'leg'
380
- end
381
- @kid.lug.should == 'leg'
382
- end
383
-
384
- it "should work when a grandchild config is added later" do
385
- class Grandkid
386
- include Dragonfly::Configurable
387
- configurable_attr :oogie, 'boogie'
388
- end
389
- grandkid = Grandkid.new
390
- grandkid.use_as_fallback_config(@kid)
391
- @dad.configure{|c| c.oogie = 'duggen' }
392
- grandkid.oogie.should == 'duggen'
393
- end
133
+ let (:car_class) { Class.new do
134
+ extend Dragonfly::Configurable
135
+ attr_accessor :colour
136
+ end }
394
137
 
395
- it "should allow configuring twice through the fallback object" do
396
- @dad.configure{|c| c.lug = 'leg' }
397
- @dad.configure{|c| c.lug = 'blug' }
398
- @kid.lug.should == 'blug'
138
+ it "adds the set_up_config method to the class" do
139
+ car_class.set_up_config do
140
+ writer :colour
399
141
  end
400
142
  end
401
-
402
- describe "clashing with configurable modules" do
403
- before(:each) do
404
- @mod = mod = Module.new
405
- @mod.module_eval do
406
- include Dragonfly::Configurable
407
- configurable_attr :team, 'spurs'
408
- end
409
- @class = Class.new
410
- @class.class_eval do
411
- include mod
412
- include Dragonfly::Configurable
413
- configurable_attr :tree, 'elm'
414
- end
415
- end
416
-
417
- it "should not override the defaults from the module" do
418
- obj = @class.new
419
- obj.team.should == 'spurs'
143
+
144
+ it "adds the configure method to the instance" do
145
+ car_class.set_up_config do
146
+ writer :colour
420
147
  end
421
-
422
- it "should still use its own defaults" do
423
- obj = @class.new
424
- obj.tree.should == 'elm'
148
+ car = car_class.new
149
+ car.should_receive(:colour=).with('mauve')
150
+ car.configure do
151
+ colour 'mauve'
425
152
  end
426
-
427
- describe "when the configurable_attr is specified in a subclass that doesn't include Configurable" do
428
- before(:each) do
429
- @subclass = Class.new(@class)
430
- @subclass.class_eval do
431
- configurable_attr :car, 'mazda'
432
- configurable_attr :tree, 'oak'
433
- end
434
- @obj = @subclass.new
435
- end
436
-
437
- it "should still work with default values" do
438
- @obj.car.should == 'mazda'
439
- end
153
+ end
440
154
 
441
- it "should override the default from the parent" do
442
- @obj.tree.should == 'oak'
443
- end
155
+ it "adds the plugins method to the instance" do
156
+ car_class.set_up_config do
157
+ writer :colour
444
158
  end
159
+ car = car_class.new
160
+ car.plugins.should == {}
161
+ end
445
162
 
163
+ it "doesn't allow configuring if the class hasn't been set up" do
164
+ car = car_class.new
165
+ expect{
166
+ car.configure{}
167
+ }.to raise_error(NoMethodError)
446
168
  end
447
-
169
+
448
170
  end
449
171
 
450
- describe "inheriting configurable_attrs from multiple places" do
172
+ describe "nested configures" do
173
+
451
174
  before(:each) do
452
- module A
453
- include Dragonfly::Configurable
454
- configurable_attr :a
455
- end
456
- module B
457
- include Dragonfly::Configurable
458
- configurable_attr :b
459
- end
460
- class K
461
- include Dragonfly::Configurable
462
- include A
463
- include B
464
- configurable_attr :c
175
+ @car_class = Class.new do
176
+ extend Dragonfly::Configurable
177
+ def initialize
178
+ @numbers = []
179
+ end
180
+ attr_accessor :numbers
465
181
  end
466
- class L < K
182
+ @car_class.set_up_config do
183
+ def add(number)
184
+ obj.numbers << number
185
+ end
467
186
  end
468
187
  end
469
-
470
- it "should include configuration from all of its mixins" do
471
- l = L.new
472
- l.configure do |c|
473
- c.a = 'something'
474
- c.b = 'something'
475
- c.c = 'something'
188
+
189
+ it "should still work (as some plugins will configure inside a configure)" do
190
+ car = @car_class.new
191
+ car.configure do
192
+ add 1
193
+ car.configure do
194
+ add 2
195
+ end
196
+ add 3
476
197
  end
198
+ car.numbers.should == [1,2,3]
477
199
  end
478
200
  end
201
+
479
202
  end
203
+