dragonfly 0.8.6 → 0.9.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.
- data/{.specopts → .rspec} +0 -1
- data/.yardopts +6 -2
- data/Gemfile +14 -13
- data/History.md +47 -9
- data/README.md +25 -5
- data/Rakefile +37 -79
- data/VERSION +1 -1
- data/dragonfly.gemspec +140 -89
- data/extra_docs/Analysers.md +8 -48
- data/extra_docs/Configuration.md +40 -25
- data/extra_docs/Couch.md +49 -0
- data/extra_docs/DataStorage.md +94 -24
- data/extra_docs/Encoding.md +6 -35
- data/extra_docs/ExampleUseCases.md +113 -0
- data/extra_docs/GeneralUsage.md +7 -23
- data/extra_docs/Generators.md +15 -49
- data/extra_docs/Heroku.md +7 -8
- data/extra_docs/ImageMagick.md +126 -0
- data/extra_docs/MimeTypes.md +3 -3
- data/extra_docs/Models.md +163 -0
- data/extra_docs/Mongo.md +1 -4
- data/extra_docs/Processing.md +7 -60
- data/extra_docs/Rails2.md +3 -1
- data/extra_docs/Rails3.md +2 -10
- data/extra_docs/ServingRemotely.md +83 -0
- data/extra_docs/Sinatra.md +3 -3
- data/extra_docs/URLs.md +60 -33
- data/features/rails_3.0.5.feature +8 -0
- data/features/steps/rails_steps.rb +7 -18
- data/features/support/env.rb +10 -37
- data/features/support/setup.rb +32 -0
- data/fixtures/rails_3.0.5/files/app/models/album.rb +5 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
- data/fixtures/{files → rails_3.0.5/files}/app/views/albums/show.html.erb +2 -0
- data/fixtures/{files → rails_3.0.5/files}/config/initializers/dragonfly.rb +0 -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/{files → rails_3.0.5/files}/features/step_definitions/image_steps.rb +11 -1
- data/fixtures/{files → rails_3.0.5/files}/features/support/paths.rb +2 -0
- data/fixtures/{files → rails_3.0.5/files}/features/text_images.feature +0 -0
- data/fixtures/{rails_3.0.3 → rails_3.0.5}/template.rb +2 -2
- data/irbrc.rb +2 -1
- data/lib/dragonfly.rb +7 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +134 -46
- data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +144 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +62 -9
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +2 -2
- data/lib/dragonfly/active_model_extensions/validations.rb +10 -6
- data/lib/dragonfly/analyser.rb +0 -1
- data/lib/dragonfly/analysis/file_command_analyser.rb +1 -1
- data/lib/dragonfly/analysis/image_magick_analyser.rb +2 -43
- data/lib/dragonfly/app.rb +64 -55
- data/lib/dragonfly/config/heroku.rb +1 -1
- data/lib/dragonfly/config/image_magick.rb +2 -37
- data/lib/dragonfly/config/rails.rb +5 -2
- data/lib/dragonfly/configurable.rb +115 -35
- data/lib/dragonfly/core_ext/object.rb +1 -1
- data/lib/dragonfly/core_ext/string.rb +1 -1
- data/lib/dragonfly/data_storage/couch_data_store.rb +84 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +43 -18
- data/lib/dragonfly/data_storage/mongo_data_store.rb +8 -4
- data/lib/dragonfly/data_storage/s3data_store.rb +82 -38
- data/lib/dragonfly/encoding/image_magick_encoder.rb +2 -53
- data/lib/dragonfly/function_manager.rb +4 -2
- data/lib/dragonfly/generation/image_magick_generator.rb +2 -136
- 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 +44 -0
- data/lib/dragonfly/{encoding/r_magick_encoder.rb → image_magick/encoder.rb} +10 -14
- data/lib/dragonfly/image_magick/generator.rb +145 -0
- data/lib/dragonfly/image_magick/processor.rb +104 -0
- data/lib/dragonfly/image_magick/utils.rb +72 -0
- data/lib/dragonfly/image_magick_utils.rb +2 -79
- data/lib/dragonfly/job.rb +152 -90
- data/lib/dragonfly/middleware.rb +5 -19
- data/lib/dragonfly/processing/image_magick_processor.rb +2 -95
- data/lib/dragonfly/rails/images.rb +15 -10
- data/lib/dragonfly/response.rb +26 -12
- data/lib/dragonfly/serializer.rb +1 -4
- data/lib/dragonfly/server.rb +103 -0
- data/lib/dragonfly/temp_object.rb +56 -101
- data/lib/dragonfly/url_mapper.rb +78 -0
- data/spec/dragonfly/active_model_extensions/model_spec.rb +772 -65
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +90 -10
- data/spec/dragonfly/analyser_spec.rb +1 -1
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +5 -14
- data/spec/dragonfly/app_spec.rb +35 -180
- data/spec/dragonfly/configurable_spec.rb +259 -18
- data/spec/dragonfly/core_ext/string_spec.rb +2 -2
- data/spec/dragonfly/core_ext/symbol_spec.rb +1 -1
- data/spec/dragonfly/data_storage/couch_data_store_spec.rb +84 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +149 -22
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +21 -2
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +207 -43
- data/spec/dragonfly/data_storage/{data_store_spec.rb → shared_data_store_examples.rb} +16 -15
- data/spec/dragonfly/function_manager_spec.rb +2 -2
- data/spec/dragonfly/{generation/hash_with_css_style_keys_spec.rb → hash_with_css_style_keys_spec.rb} +2 -2
- data/spec/dragonfly/{analysis/shared_analyser_spec.rb → image_magick/analyser_spec.rb} +19 -6
- data/spec/dragonfly/{encoding/image_magick_encoder_spec.rb → image_magick/encoder_spec.rb} +2 -2
- data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
- data/spec/dragonfly/{processing/shared_processing_spec.rb → image_magick/processor_spec.rb} +55 -6
- data/spec/dragonfly/image_magick/utils_spec.rb +18 -0
- data/spec/dragonfly/job_builder_spec.rb +1 -1
- data/spec/dragonfly/job_definitions_spec.rb +1 -1
- data/spec/dragonfly/job_endpoint_spec.rb +26 -3
- data/spec/dragonfly/job_spec.rb +426 -208
- data/spec/dragonfly/loggable_spec.rb +2 -2
- data/spec/dragonfly/middleware_spec.rb +5 -26
- data/spec/dragonfly/routed_endpoint_spec.rb +1 -1
- data/spec/dragonfly/serializer_spec.rb +1 -14
- data/spec/dragonfly/server_spec.rb +261 -0
- data/spec/dragonfly/simple_cache_spec.rb +1 -1
- data/spec/dragonfly/temp_object_spec.rb +84 -130
- data/spec/dragonfly/url_mapper_spec.rb +130 -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 +12 -22
- data/spec/{argument_matchers.rb → support/argument_matchers.rb} +0 -0
- data/spec/{image_matchers.rb → support/image_matchers.rb} +4 -4
- data/spec/support/simple_matchers.rb +53 -0
- data/yard/handlers/configurable_attr_handler.rb +2 -2
- data/yard/templates/default/fulldoc/html/css/common.css +12 -10
- data/yard/templates/default/layout/html/layout.erb +6 -0
- metadata +267 -308
- data/Gemfile.rails.2.3.5 +0 -20
- data/features/3.0.3.feature +0 -8
- data/features/rails_2.3.5.feature +0 -7
- data/fixtures/files/app/models/album.rb +0 -3
- data/fixtures/files/app/views/albums/new.html.erb +0 -4
- data/fixtures/files/features/manage_album_images.feature +0 -12
- data/fixtures/rails_2.3.5/template.rb +0 -10
- data/lib/dragonfly/analysis/r_magick_analyser.rb +0 -63
- data/lib/dragonfly/config/r_magick.rb +0 -46
- data/lib/dragonfly/generation/hash_with_css_style_keys.rb +0 -23
- data/lib/dragonfly/generation/r_magick_generator.rb +0 -155
- data/lib/dragonfly/processing/r_magick_processor.rb +0 -126
- data/lib/dragonfly/r_magick_utils.rb +0 -48
- data/lib/dragonfly/simple_endpoint.rb +0 -76
- data/spec/dragonfly/active_model_extensions/active_model_setup.rb +0 -97
- data/spec/dragonfly/active_model_extensions/active_record_setup.rb +0 -85
- data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +0 -15
- data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +0 -31
- data/spec/dragonfly/config/r_magick_spec.rb +0 -29
- data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +0 -41
- data/spec/dragonfly/generation/image_magick_generator_spec.rb +0 -12
- data/spec/dragonfly/generation/r_magick_generator_spec.rb +0 -28
- data/spec/dragonfly/generation/shared_generator_spec.rb +0 -91
- data/spec/dragonfly/image_magick_utils_spec.rb +0 -16
- data/spec/dragonfly/processing/image_magick_processor_spec.rb +0 -29
- data/spec/dragonfly/processing/r_magick_processor_spec.rb +0 -30
- data/spec/dragonfly/simple_endpoint_spec.rb +0 -97
- data/spec/simple_matchers.rb +0 -44
@@ -0,0 +1,78 @@
|
|
1
|
+
module Dragonfly
|
2
|
+
class UrlMapper
|
3
|
+
|
4
|
+
# Exceptions
|
5
|
+
class BadUrlFormat < StandardError; end
|
6
|
+
|
7
|
+
class Segment < Struct.new(:param, :seperator, :pattern)
|
8
|
+
|
9
|
+
def regexp_string
|
10
|
+
@regexp_string ||= "(#{Regexp.escape(seperator)}#{pattern}+?)?"
|
11
|
+
end
|
12
|
+
#
|
13
|
+
# def regexp
|
14
|
+
# @regexp ||= Regexp.new(regexp_string)
|
15
|
+
# end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(url_format, patterns={})
|
20
|
+
@url_format = url_format
|
21
|
+
raise BadUrlFormat, "bad url format #{url_format}" if url_format[/[\w_]:[\w_]/]
|
22
|
+
init_segments(patterns)
|
23
|
+
init_url_regexp
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :url_format, :url_regexp, :segments
|
27
|
+
|
28
|
+
def params_for(path, query=nil)
|
29
|
+
if path and md = path.match(url_regexp)
|
30
|
+
params = Rack::Utils.parse_query(query)
|
31
|
+
params_in_url.each_with_index do |var, i|
|
32
|
+
value = md[i+1][1..-1] if md[i+1]
|
33
|
+
params[var] = value
|
34
|
+
end
|
35
|
+
params
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def params_in_url
|
40
|
+
@params_in_url ||= url_format.scan(/\:[\w_]+/).map{|f| f.tr(':','') }
|
41
|
+
end
|
42
|
+
|
43
|
+
def url_for(params)
|
44
|
+
params = params.dup
|
45
|
+
url = url_format.dup
|
46
|
+
segments.each do |seg|
|
47
|
+
value = params[seg.param]
|
48
|
+
value ? url.sub!(/:[\w_]+/, value.to_s) : url.sub!(/.:[\w_]+/, '')
|
49
|
+
params.delete(seg.param)
|
50
|
+
end
|
51
|
+
url << "?#{Rack::Utils.build_query(params)}" if params.any?
|
52
|
+
url
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def init_segments(patterns)
|
58
|
+
@segments = []
|
59
|
+
url_format.scan(/([^\w_]):([\w_]+)/).each do |seperator, param|
|
60
|
+
segments << Segment.new(
|
61
|
+
param,
|
62
|
+
seperator,
|
63
|
+
patterns[param.to_sym] || '[^\/\-\.]'
|
64
|
+
)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def init_url_regexp
|
69
|
+
i = -1
|
70
|
+
regexp_string = url_format.gsub(/[^\w_]:[\w_]+/) do
|
71
|
+
i += 1
|
72
|
+
segments[i].regexp_string
|
73
|
+
end
|
74
|
+
@url_regexp = Regexp.new('^' + regexp_string + '$')
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -1,22 +1,52 @@
|
|
1
|
-
require
|
1
|
+
require 'dragonfly/active_model_extensions/spec_helper'
|
2
2
|
|
3
3
|
describe Item do
|
4
4
|
|
5
|
+
def set_up_item_class(app=test_app)
|
6
|
+
app.define_macro(MyModel, :image_accessor)
|
7
|
+
Item.class_eval do
|
8
|
+
image_accessor :preview_image
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
5
12
|
# See extra setup in models / initializer files
|
6
13
|
|
7
14
|
describe "defining accessors" do
|
8
15
|
|
9
|
-
let(:app1){ Dragonfly[:
|
10
|
-
let(:app2){ Dragonfly[:
|
16
|
+
let(:app1){ Dragonfly[:img] }
|
17
|
+
let(:app2){ Dragonfly[:vid] }
|
11
18
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
19
|
+
describe "attachment classes" do
|
20
|
+
before(:each) do
|
21
|
+
app1.define_macro(MyModel, :image_accessor)
|
22
|
+
app2.define_macro(MyModel, :video_accessor)
|
23
|
+
Item.class_eval do
|
24
|
+
image_accessor :preview_image
|
25
|
+
video_accessor :trailer_video
|
26
|
+
end
|
27
|
+
@classes = Item.dragonfly_attachment_classes
|
28
|
+
@class1, @class2 = @classes
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return the attachment classes" do
|
32
|
+
@class1.superclass.should == Dragonfly::ActiveModelExtensions::Attachment
|
33
|
+
@class2.superclass.should == Dragonfly::ActiveModelExtensions::Attachment
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should associate the correct app with each class" do
|
37
|
+
@class1.app.should == app1
|
38
|
+
@class2.app.should == app2
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should associate the correct attribute with each class" do
|
42
|
+
@class1.attribute.should == :preview_image
|
43
|
+
@class2.attribute.should == :trailer_video
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should associate the correct model class with each class" do
|
47
|
+
@class1.model_class.should == Item
|
48
|
+
@class2.model_class.should == Item
|
18
49
|
end
|
19
|
-
Item.dragonfly_apps_for_attributes.should == {:preview_image => app1, :trailer_video => app2}
|
20
50
|
end
|
21
51
|
|
22
52
|
it "should work for included modules (e.g. Mongoid::Document)" do
|
@@ -28,7 +58,9 @@ describe Item do
|
|
28
58
|
include mongoid_document
|
29
59
|
dog_accessor :doogie
|
30
60
|
end
|
31
|
-
model_class.
|
61
|
+
klass = model_class.dragonfly_attachment_classes.first
|
62
|
+
klass.app.should == app1
|
63
|
+
klass.attribute.should == :doogie
|
32
64
|
end
|
33
65
|
|
34
66
|
end
|
@@ -36,8 +68,8 @@ describe Item do
|
|
36
68
|
describe "correctly defined" do
|
37
69
|
|
38
70
|
before(:each) do
|
39
|
-
@app =
|
40
|
-
@app.define_macro(
|
71
|
+
@app = test_app
|
72
|
+
@app.define_macro(MyModel, :image_accessor)
|
41
73
|
Item.class_eval do
|
42
74
|
image_accessor :preview_image
|
43
75
|
end
|
@@ -102,7 +134,7 @@ describe Item do
|
|
102
134
|
@item.preview_image_uid.should be_nil
|
103
135
|
end
|
104
136
|
it "should store the image when saved" do
|
105
|
-
@app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"),
|
137
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"), hash_including)
|
106
138
|
@item.save!
|
107
139
|
end
|
108
140
|
it "should not try to destroy anything on destroy" do
|
@@ -136,7 +168,7 @@ describe Item do
|
|
136
168
|
|
137
169
|
before(:each) do
|
138
170
|
@item.preview_image = "DATASTRING"
|
139
|
-
@app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"),
|
171
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"), hash_including).once.and_return('some_uid')
|
140
172
|
@item.save!
|
141
173
|
end
|
142
174
|
|
@@ -159,8 +191,7 @@ describe Item do
|
|
159
191
|
end
|
160
192
|
|
161
193
|
it "should return the url for the data" do
|
162
|
-
@
|
163
|
-
@item.preview_image.url.should == 'some.url'
|
194
|
+
@item.preview_image.url.should =~ %r<^/\w+$>
|
164
195
|
end
|
165
196
|
|
166
197
|
it "should destroy the old data when the uid is set manually" do
|
@@ -203,7 +234,7 @@ describe Item do
|
|
203
234
|
@item.save!
|
204
235
|
end
|
205
236
|
it "should store the new data when saved" do
|
206
|
-
@app.datastore.should_receive(:store).with(a_temp_object_with_data("ANEWDATASTRING"),
|
237
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data("ANEWDATASTRING"), hash_including)
|
207
238
|
@item.save!
|
208
239
|
end
|
209
240
|
it "should destroy the old data on destroy" do
|
@@ -329,13 +360,25 @@ describe Item do
|
|
329
360
|
end
|
330
361
|
end
|
331
362
|
|
363
|
+
describe "remote_url" do
|
364
|
+
it "should give the remote url if the uid is set" do
|
365
|
+
@item.preview_image_uid = 'some/uid'
|
366
|
+
@app.should_receive(:remote_url_for).with('some/uid', :some => 'param').and_return('http://egg.nog')
|
367
|
+
@item.preview_image.remote_url(:some => 'param').should == 'http://egg.nog'
|
368
|
+
end
|
369
|
+
it "should return nil if the content is not yet saved" do
|
370
|
+
@item.preview_image = "hello"
|
371
|
+
@item.preview_image.remote_url(:some => 'param').should be_nil
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
332
375
|
end
|
333
376
|
|
334
377
|
describe "validations" do
|
335
378
|
|
336
379
|
before(:all) do
|
337
|
-
@app =
|
338
|
-
@app.define_macro(
|
380
|
+
@app = test_app
|
381
|
+
@app.define_macro(MyModel, :image_accessor)
|
339
382
|
end
|
340
383
|
|
341
384
|
describe "validates_presence_of" do
|
@@ -424,27 +467,27 @@ describe Item do
|
|
424
467
|
it "should be invalid if the property is nil" do
|
425
468
|
@item.preview_image = "OTHER TYPE"
|
426
469
|
@item.should_not be_valid
|
427
|
-
@item.errors[:preview_image].should
|
470
|
+
@item.errors[:preview_image].should == ["mime type is incorrect. It needs to be one of 'how/special', 'how/crazy', but was 'application/octet-stream'"]
|
428
471
|
end
|
429
472
|
|
430
473
|
it "should be invalid if the property is wrong" do
|
431
474
|
@item.preview_image = "WRONG TYPE"
|
432
475
|
@item.should_not be_valid
|
433
|
-
@item.errors[:preview_image].should
|
476
|
+
@item.errors[:preview_image].should == ["mime type is incorrect. It needs to be one of 'how/special', 'how/crazy', but was 'wrong/type'"]
|
434
477
|
end
|
435
478
|
|
436
479
|
it "should work for a range" do
|
437
480
|
@item.preview_image = "GOOGLE GUM"
|
438
481
|
@item.should_not be_valid
|
439
|
-
@item.errors[:preview_image].should
|
482
|
+
@item.errors[:preview_image].should == ["number of gs is incorrect. It needs to be between 0 and 2, but was '3'"]
|
440
483
|
end
|
441
484
|
|
442
485
|
it "should validate individually" do
|
443
486
|
@item.other_image = "1234567"
|
444
487
|
@item.yet_another_image = "WRONG TYPE"
|
445
488
|
@item.should_not be_valid
|
446
|
-
@item.errors[:other_image].should
|
447
|
-
@item.errors[:yet_another_image].should
|
489
|
+
@item.errors[:other_image].should == []
|
490
|
+
@item.errors[:yet_another_image].should == ["mime type is incorrect. It needs to be 'how/special', but was 'wrong/type'"]
|
448
491
|
end
|
449
492
|
|
450
493
|
it "should include standard extra options like 'if' on mime type validation" do
|
@@ -472,7 +515,19 @@ describe Item do
|
|
472
515
|
it "should allow for custom messages" do
|
473
516
|
@item.otra_imagen = "WRONG TYPE"
|
474
517
|
@item.should_not be_valid
|
475
|
-
@item.errors[:otra_imagen].should
|
518
|
+
@item.errors[:otra_imagen].should == ["tipo de contenido incorrecto. Que chungo tio"]
|
519
|
+
end
|
520
|
+
|
521
|
+
it "should allow for custom messages including access to the property name and expected/allowed values" do
|
522
|
+
@item.should_receive(:its_friday).and_return(false) # hack to get rid of other validation
|
523
|
+
Item.class_eval do
|
524
|
+
validates_property :mime_type, :of => :preview_image, :as => 'one/thing',
|
525
|
+
:message => proc{|actual, model| "Unlucky #{model.title}! Was #{actual}" }
|
526
|
+
end
|
527
|
+
@item.title = 'scubby'
|
528
|
+
@item.preview_image = "WRONG TYPE"
|
529
|
+
@item.should_not be_valid
|
530
|
+
@item.errors[:preview_image].should == ["Unlucky scubby! Was wrong/type"]
|
476
531
|
end
|
477
532
|
|
478
533
|
end
|
@@ -482,7 +537,7 @@ describe Item do
|
|
482
537
|
describe "extra properties" do
|
483
538
|
|
484
539
|
before(:each) do
|
485
|
-
@app =
|
540
|
+
@app = test_app
|
486
541
|
custom_analyser = Class.new do
|
487
542
|
def some_analyser_method(temp_object)
|
488
543
|
"abc" + temp_object.data[0..0]
|
@@ -490,7 +545,7 @@ describe Item do
|
|
490
545
|
def number_of_As(temp_object); temp_object.data.count('A'); end
|
491
546
|
end
|
492
547
|
@app.analyser.register(custom_analyser)
|
493
|
-
@app.define_macro(
|
548
|
+
@app.define_macro(MyModel, :image_accessor)
|
494
549
|
Item.class_eval do
|
495
550
|
image_accessor :preview_image
|
496
551
|
end
|
@@ -520,12 +575,6 @@ describe Item do
|
|
520
575
|
@item.preview_image_some_analyser_method.should == 'abc4'
|
521
576
|
end
|
522
577
|
|
523
|
-
it "should reset the magic attribute when set to nil" do
|
524
|
-
@item.preview_image = '123'
|
525
|
-
@item.preview_image = nil
|
526
|
-
@item.preview_image_some_analyser_method.should be_nil
|
527
|
-
end
|
528
|
-
|
529
578
|
it "should not reset non-magic attributes with the same prefix when set to nil" do
|
530
579
|
@item.preview_image_blah_blah = 'wassup'
|
531
580
|
@item.preview_image = '123'
|
@@ -538,21 +587,53 @@ describe Item do
|
|
538
587
|
@item.preview_image_size.should == 3
|
539
588
|
end
|
540
589
|
|
541
|
-
it "should store the original file
|
590
|
+
it "should store the original file name if it exists" do
|
542
591
|
data = 'jasdlkf sadjl'
|
543
592
|
data.stub!(:original_filename).and_return('hello.png')
|
544
593
|
@item.preview_image = data
|
545
|
-
@item.
|
594
|
+
@item.preview_image_name.should == 'hello.png'
|
546
595
|
end
|
547
596
|
|
548
|
-
|
597
|
+
end
|
598
|
+
|
599
|
+
describe "meta from magic attributes" do
|
600
|
+
|
601
|
+
it "should set the meta for the magic attribute when assigned" do
|
602
|
+
@item.preview_image = '123'
|
603
|
+
@item.preview_image.meta[:some_analyser_method].should == 'abc1'
|
604
|
+
end
|
605
|
+
|
606
|
+
it "should not set meta for non-magic attributes with the same prefix when assigned" do
|
607
|
+
@item.preview_image = '123'
|
608
|
+
@item.preview_image.meta[:blah_blah].should be_nil
|
609
|
+
end
|
610
|
+
|
611
|
+
it "should update the meta for the magic attribute when something else is assigned" do
|
612
|
+
@item.preview_image = '123'
|
613
|
+
@item.preview_image = '456'
|
614
|
+
@item.preview_image.meta[:some_analyser_method].should == 'abc4'
|
615
|
+
end
|
616
|
+
|
617
|
+
it "should include the meta for size too" do
|
618
|
+
@item.preview_image = '123'
|
619
|
+
@item.preview_image.meta[:size].should == 3
|
620
|
+
end
|
621
|
+
|
622
|
+
it "should store the meta for the original file name if it exists" do
|
549
623
|
data = 'jasdlkf sadjl'
|
550
624
|
data.stub!(:original_filename).and_return('hello.png')
|
551
625
|
@item.preview_image = data
|
552
|
-
@item.
|
626
|
+
@item.preview_image.meta[:name].should == 'hello.png'
|
627
|
+
end
|
628
|
+
|
629
|
+
it "should still have the meta after reload" do
|
630
|
+
@item.preview_image = '123'
|
631
|
+
@item.save!
|
632
|
+
item = Item.find(@item.id)
|
633
|
+
item.preview_image.meta[:some_analyser_method].should == 'abc1'
|
553
634
|
end
|
554
|
-
end
|
555
635
|
|
636
|
+
end
|
556
637
|
|
557
638
|
describe "delegating methods to the job" do
|
558
639
|
before(:each) do
|
@@ -588,22 +669,20 @@ describe Item do
|
|
588
669
|
end
|
589
670
|
it "should use the magic attribute if there is one, and not load the content" do
|
590
671
|
@app.datastore.should_not_receive(:retrieve)
|
591
|
-
@item.should_receive(:preview_image_some_analyser_method).and_return('result yo')
|
672
|
+
@item.should_receive(:preview_image_some_analyser_method).at_least(:once).and_return('result yo')
|
592
673
|
@item.preview_image.some_analyser_method.should == 'result yo'
|
593
674
|
end
|
594
675
|
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
end
|
676
|
+
it "should use the magic attribute for size if there is one, and not the job object" do
|
677
|
+
@item.preview_image.send(:job).should_not_receive(:size)
|
678
|
+
@item.should_receive("preview_image_size").and_return(17)
|
679
|
+
@item.preview_image.size.should == 17
|
680
|
+
end
|
601
681
|
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
end
|
682
|
+
it "should delegate 'size' to the job object if there is no magic attribute for it" do
|
683
|
+
@item.other_image = 'blahdata'
|
684
|
+
@item.other_image.send(:job).should_receive(:size).and_return 54
|
685
|
+
@item.other_image.size.should == 54
|
607
686
|
end
|
608
687
|
|
609
688
|
end
|
@@ -615,6 +694,19 @@ describe Item do
|
|
615
694
|
}.should raise_error(NoMethodError)
|
616
695
|
end
|
617
696
|
end
|
697
|
+
|
698
|
+
describe "job shortcuts" do
|
699
|
+
before(:each) do
|
700
|
+
@app.job :bacon do
|
701
|
+
process :breakfast
|
702
|
+
end
|
703
|
+
@item = Item.new :preview_image => 'gurg'
|
704
|
+
end
|
705
|
+
it "should add job shortcuts for that app" do
|
706
|
+
job = @item.preview_image.bacon
|
707
|
+
job.steps.first.should be_a(Dragonfly::Job::Process)
|
708
|
+
end
|
709
|
+
end
|
618
710
|
|
619
711
|
describe "setting things on the attachment" do
|
620
712
|
|
@@ -636,6 +728,9 @@ describe Item do
|
|
636
728
|
it "should return the name" do
|
637
729
|
(@item.preview_image.name = 'no.silly').should == 'no.silly'
|
638
730
|
end
|
731
|
+
it "should update the ext too" do
|
732
|
+
@item.preview_image.ext.should == 'there'
|
733
|
+
end
|
639
734
|
end
|
640
735
|
|
641
736
|
describe "meta" do
|
@@ -656,12 +751,12 @@ describe Item do
|
|
656
751
|
it "should save it correctly" do
|
657
752
|
@item.save!
|
658
753
|
item = Item.find(@item.id)
|
659
|
-
item.preview_image.meta.should include_hash(:slime => 'balls')
|
754
|
+
item.preview_image.apply.meta.should include_hash(:slime => 'balls')
|
660
755
|
end
|
661
|
-
it "should
|
756
|
+
it "should include meta info about the model" do
|
662
757
|
@item.save!
|
663
|
-
|
664
|
-
|
758
|
+
item = Item.find(@item.id)
|
759
|
+
item.preview_image.meta.should include_hash(:model_class => 'Item', :model_attachment => :preview_image)
|
665
760
|
end
|
666
761
|
end
|
667
762
|
|
@@ -672,10 +767,10 @@ describe Item do
|
|
672
767
|
describe "inheritance" do
|
673
768
|
|
674
769
|
before(:all) do
|
675
|
-
@app =
|
676
|
-
@app2 =
|
677
|
-
@app.define_macro(
|
678
|
-
@app2.define_macro(
|
770
|
+
@app = test_app
|
771
|
+
@app2 = test_app
|
772
|
+
@app.define_macro(MyModel, :image_accessor)
|
773
|
+
@app2.define_macro(MyModel, :egg_accessor)
|
679
774
|
Car.class_eval do
|
680
775
|
image_accessor :image
|
681
776
|
end
|
@@ -712,12 +807,624 @@ describe Item do
|
|
712
807
|
it "should allow assigning subclass accessors in the subclass, even if it has mixins" do
|
713
808
|
@subclass_with_module.create! :reliant_image => 'blah'
|
714
809
|
end
|
715
|
-
it "return the correct
|
716
|
-
@base_class.
|
717
|
-
|
718
|
-
|
719
|
-
@
|
810
|
+
it "should return the correct attachment classes for the base class" do
|
811
|
+
@base_class.dragonfly_attachment_classes.should match_attachment_classes([[Car, :image, @app]])
|
812
|
+
end
|
813
|
+
it "should return the correct attachment classes for the subclass" do
|
814
|
+
@subclass.dragonfly_attachment_classes.should match_attachment_classes([[ReliantRobin, :image, @app], [ReliantRobin, :reliant_image, @app]])
|
815
|
+
end
|
816
|
+
it "should return the correct attachment classes for the subclass with module" do
|
817
|
+
@subclass_with_module.dragonfly_attachment_classes.should match_attachment_classes([[ReliantRobinWithModule, :image, @app], [ReliantRobinWithModule, :reliant_image, @app]])
|
818
|
+
end
|
819
|
+
it "should return the correct attachment classes for a class from a different hierarchy" do
|
820
|
+
@unrelated_class.dragonfly_attachment_classes.should match_attachment_classes([[Photo, :image, @app2]])
|
821
|
+
end
|
822
|
+
end
|
823
|
+
|
824
|
+
describe "setting the url" do
|
825
|
+
before(:each) do
|
826
|
+
set_up_item_class
|
827
|
+
@item = Item.new
|
828
|
+
stub_request(:get, "http://some.url/yo.png").to_return(:body => "aaaaayo")
|
829
|
+
end
|
830
|
+
|
831
|
+
it "should allow setting the url" do
|
832
|
+
@item.preview_image_url = 'http://some.url/yo.png'
|
833
|
+
@item.preview_image.data.should == 'aaaaayo'
|
834
|
+
end
|
835
|
+
it "should return nil always for the reader" do
|
836
|
+
@item.preview_image_url = 'http://some.url/yo.png'
|
837
|
+
@item.preview_image_url.should be_nil
|
838
|
+
end
|
839
|
+
it "should have set the name" do
|
840
|
+
@item.preview_image_url = 'http://some.url/yo.png'
|
841
|
+
@item.preview_image_name.should == 'yo.png'
|
842
|
+
@item.preview_image.meta[:name].should == 'yo.png'
|
843
|
+
end
|
844
|
+
[nil, ""].each do |value|
|
845
|
+
it "should do nothing if set with #{value.inspect}" do
|
846
|
+
@item.preview_image_url = value
|
847
|
+
@item.preview_image.should be_nil
|
848
|
+
end
|
849
|
+
end
|
850
|
+
end
|
851
|
+
|
852
|
+
describe "removing the accessor with e.g. a form" do
|
853
|
+
before(:each) do
|
854
|
+
set_up_item_class
|
855
|
+
@item = Item.new
|
856
|
+
@item.preview_image = "something"
|
857
|
+
end
|
858
|
+
|
859
|
+
[
|
860
|
+
1,
|
861
|
+
"1",
|
862
|
+
true,
|
863
|
+
"true",
|
864
|
+
"blahblah"
|
865
|
+
].each do |value|
|
866
|
+
it "should remove the accessor if passed #{value.inspect}" do
|
867
|
+
@item.remove_preview_image = value
|
868
|
+
@item.preview_image.should be_nil
|
869
|
+
end
|
870
|
+
|
871
|
+
it "should return true when called if set with #{value.inspect}" do
|
872
|
+
@item.remove_preview_image = value
|
873
|
+
@item.remove_preview_image.should be_true
|
874
|
+
end
|
875
|
+
end
|
876
|
+
|
877
|
+
[
|
878
|
+
0,
|
879
|
+
"0",
|
880
|
+
false,
|
881
|
+
"false",
|
882
|
+
"",
|
883
|
+
nil
|
884
|
+
].each do |value|
|
885
|
+
it "should not remove the accessor if passed #{value.inspect}" do
|
886
|
+
@item.remove_preview_image = value
|
887
|
+
@item.preview_image.should_not be_nil
|
888
|
+
end
|
889
|
+
|
890
|
+
it "should return false when called if set with #{value.inspect}" do
|
891
|
+
@item.remove_preview_image = value
|
892
|
+
@item.remove_preview_image.should be_false
|
893
|
+
end
|
894
|
+
end
|
895
|
+
|
896
|
+
it "should return false by default for the getter" do
|
897
|
+
@item.remove_preview_image.should be_false
|
898
|
+
end
|
899
|
+
|
900
|
+
end
|
901
|
+
|
902
|
+
describe "callbacks" do
|
903
|
+
|
904
|
+
describe "after_assign" do
|
905
|
+
|
906
|
+
before(:each) do
|
907
|
+
@app = test_app
|
908
|
+
@app.define_macro(MyModel, :image_accessor)
|
909
|
+
end
|
910
|
+
|
911
|
+
describe "as a block" do
|
912
|
+
|
913
|
+
def set_after_assign(*args, &block)
|
914
|
+
Item.class_eval do
|
915
|
+
image_accessor :preview_image do
|
916
|
+
after_assign(*args, &block)
|
917
|
+
end
|
918
|
+
end
|
919
|
+
end
|
920
|
+
|
921
|
+
it "should call it after assign" do
|
922
|
+
x = nil
|
923
|
+
set_after_assign{ x = 3 }
|
924
|
+
Item.new.preview_image = "hello"
|
925
|
+
x.should == 3
|
926
|
+
end
|
927
|
+
|
928
|
+
it "should not call it after unassign" do
|
929
|
+
x = nil
|
930
|
+
set_after_assign{ x = 3 }
|
931
|
+
Item.new.preview_image = nil
|
932
|
+
x.should be_nil
|
933
|
+
end
|
934
|
+
|
935
|
+
it "should yield the attachment" do
|
936
|
+
x = nil
|
937
|
+
set_after_assign{|a| x = a.data }
|
938
|
+
Item.new.preview_image = "discussion"
|
939
|
+
x.should == "discussion"
|
940
|
+
end
|
941
|
+
|
942
|
+
it "should evaluate in the model context" do
|
943
|
+
x = nil
|
944
|
+
set_after_assign{ x = title.upcase }
|
945
|
+
item = Item.new
|
946
|
+
item.title = "big"
|
947
|
+
item.preview_image = "jobs"
|
948
|
+
x.should == "BIG"
|
949
|
+
end
|
950
|
+
|
951
|
+
it "should allow passing a symbol for calling a model method" do
|
952
|
+
set_after_assign :set_title
|
953
|
+
item = Item.new
|
954
|
+
def item.set_title; self.title = 'duggen'; end
|
955
|
+
item.preview_image = "jobs"
|
956
|
+
item.title.should == "duggen"
|
957
|
+
end
|
958
|
+
|
959
|
+
it "should allow passing multiple symbols" do
|
960
|
+
set_after_assign :set_title, :upcase_title
|
961
|
+
item = Item.new
|
962
|
+
def item.set_title; self.title = 'doobie'; end
|
963
|
+
def item.upcase_title; self.title.upcase!; end
|
964
|
+
item.preview_image = "jobs"
|
965
|
+
item.title.should == "DOOBIE"
|
966
|
+
end
|
967
|
+
|
968
|
+
it "should not re-trigger callbacks (causing an infinite loop)" do
|
969
|
+
set_after_assign{|a| self.preview_image = 'dogman' }
|
970
|
+
item = Item.new
|
971
|
+
item.preview_image = "hello"
|
972
|
+
end
|
973
|
+
|
974
|
+
end
|
975
|
+
|
976
|
+
end
|
977
|
+
|
978
|
+
describe "after_unassign" do
|
979
|
+
before(:each) do
|
980
|
+
@app = test_app
|
981
|
+
@app.define_macro(MyModel, :image_accessor)
|
982
|
+
Item.class_eval do
|
983
|
+
image_accessor :preview_image do
|
984
|
+
after_unassign{ self.title = 'unassigned' }
|
985
|
+
end
|
986
|
+
end
|
987
|
+
@item = Item.new :title => 'yo'
|
988
|
+
end
|
989
|
+
|
990
|
+
it "should not call it after assign" do
|
991
|
+
@item.preview_image = 'suggs'
|
992
|
+
@item.title.should == 'yo'
|
993
|
+
end
|
994
|
+
|
995
|
+
it "should call it after unassign" do
|
996
|
+
@item.preview_image = nil
|
997
|
+
@item.title.should == 'unassigned'
|
998
|
+
end
|
999
|
+
end
|
1000
|
+
|
1001
|
+
describe "copy_to" do
|
1002
|
+
before(:each) do
|
1003
|
+
@app = test_app
|
1004
|
+
@app.define_macro(MyModel, :image_accessor)
|
1005
|
+
@app.processor.add(:append) do |temp_object, string|
|
1006
|
+
temp_object.data + string
|
1007
|
+
end
|
1008
|
+
Item.class_eval do
|
1009
|
+
image_accessor :preview_image do
|
1010
|
+
copy_to(:other_image){|a| a.process(:append, title) }
|
1011
|
+
copy_to(:yet_another_image)
|
1012
|
+
end
|
1013
|
+
image_accessor :other_image
|
1014
|
+
image_accessor :yet_another_image
|
1015
|
+
end
|
1016
|
+
@item = Item.new :title => 'yo'
|
1017
|
+
end
|
1018
|
+
|
1019
|
+
it "should copy to the other image when assigned" do
|
1020
|
+
@item.preview_image = 'hello bear'
|
1021
|
+
@item.other_image.data.should == 'hello bearyo'
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
it "should remove the other image when unassigned" do
|
1025
|
+
@item.preview_image = 'hello bear'
|
1026
|
+
@item.preview_image = nil
|
1027
|
+
@item.other_image.should be_nil
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
it "should allow simply copying over without args" do
|
1031
|
+
@item.preview_image = 'hello bear'
|
1032
|
+
@item.yet_another_image.data.should == 'hello bear'
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
end
|
1036
|
+
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
describe "storage_opts" do
|
1040
|
+
|
1041
|
+
def set_storage_opts(*args, &block)
|
1042
|
+
Item.class_eval do
|
1043
|
+
image_accessor :preview_image do
|
1044
|
+
storage_opts(*args, &block)
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
end
|
1048
|
+
|
1049
|
+
before(:each) do
|
1050
|
+
@app = test_app
|
1051
|
+
@app.define_macro(MyModel, :image_accessor)
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
it "should send the specified options to the datastore on store" do
|
1055
|
+
set_storage_opts :egg => 'head'
|
1056
|
+
item = Item.new :preview_image => 'hello'
|
1057
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(:egg => 'head'))
|
1058
|
+
item.save!
|
1059
|
+
end
|
1060
|
+
|
1061
|
+
it "should allow putting in a proc" do
|
1062
|
+
set_storage_opts{ {:egg => 'numb'} }
|
1063
|
+
item = Item.new :preview_image => 'hello'
|
1064
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(:egg => 'numb'))
|
1065
|
+
item.save!
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
it "should yield the attachment and exec in model context" do
|
1069
|
+
set_storage_opts{|a| {:egg => (a.data + title)} }
|
1070
|
+
item = Item.new :title => 'lump', :preview_image => 'hello'
|
1071
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(:egg => 'hellolump'))
|
1072
|
+
item.save!
|
1073
|
+
end
|
1074
|
+
|
1075
|
+
it "should allow giving it a method symbol" do
|
1076
|
+
set_storage_opts :special_ops
|
1077
|
+
item = Item.new :preview_image => 'hello'
|
1078
|
+
def item.special_ops; {:a => 1}; end
|
1079
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(:a => 1))
|
1080
|
+
item.save!
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
it "should allow setting more than once" do
|
1084
|
+
Item.class_eval do
|
1085
|
+
image_accessor :preview_image do
|
1086
|
+
storage_opts{{ :a => title, :b => 'dumple' }}
|
1087
|
+
storage_opts{{ :b => title.upcase, :c => 'digby' }}
|
1088
|
+
end
|
1089
|
+
end
|
1090
|
+
item = Item.new :title => 'lump', :preview_image => 'hello'
|
1091
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(
|
1092
|
+
:a => 'lump', :b => 'LUMP', :c => 'digby'
|
1093
|
+
))
|
1094
|
+
item.save!
|
720
1095
|
end
|
721
1096
|
end
|
722
1097
|
|
723
|
-
|
1098
|
+
describe "storage_path, etc." do
|
1099
|
+
|
1100
|
+
def set_storage_path(path=nil, &block)
|
1101
|
+
Item.class_eval do
|
1102
|
+
image_accessor :preview_image do
|
1103
|
+
storage_path(path, &block)
|
1104
|
+
end
|
1105
|
+
def monkey
|
1106
|
+
"mr/#{title}/monkey"
|
1107
|
+
end
|
1108
|
+
end
|
1109
|
+
end
|
1110
|
+
|
1111
|
+
before(:each) do
|
1112
|
+
@app = test_app
|
1113
|
+
@app.define_macro(MyModel, :image_accessor)
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
it "should allow setting as a string" do
|
1117
|
+
set_storage_path 'always/the/same'
|
1118
|
+
item = Item.new :preview_image => 'bilbo'
|
1119
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(
|
1120
|
+
:path => 'always/the/same'
|
1121
|
+
))
|
1122
|
+
item.save!
|
1123
|
+
end
|
1124
|
+
|
1125
|
+
it "should allow setting as a symbol" do
|
1126
|
+
set_storage_path :monkey
|
1127
|
+
item = Item.new :title => 'billy'
|
1128
|
+
item.preview_image = 'bilbo'
|
1129
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(
|
1130
|
+
:path => 'mr/billy/monkey'
|
1131
|
+
))
|
1132
|
+
item.save!
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
it "should allow setting as a block" do
|
1136
|
+
set_storage_path{|a| "#{a.data}/megs/#{title}" }
|
1137
|
+
item = Item.new :title => 'billy'
|
1138
|
+
item.preview_image = 'bilbo'
|
1139
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(
|
1140
|
+
:path => 'bilbo/megs/billy'
|
1141
|
+
))
|
1142
|
+
item.save!
|
1143
|
+
end
|
1144
|
+
|
1145
|
+
it "should work for other storage_xxx declarations" do
|
1146
|
+
Item.class_eval do
|
1147
|
+
image_accessor :preview_image do
|
1148
|
+
storage_eggs 23
|
1149
|
+
end
|
1150
|
+
end
|
1151
|
+
item = Item.new :preview_image => 'bilbo'
|
1152
|
+
@app.datastore.should_receive(:store).with(anything, hash_including(
|
1153
|
+
:eggs => 23
|
1154
|
+
))
|
1155
|
+
item.save!
|
1156
|
+
end
|
1157
|
+
end
|
1158
|
+
|
1159
|
+
describe "unknown config method" do
|
1160
|
+
it "should raise an error" do
|
1161
|
+
lambda{
|
1162
|
+
Item.class_eval do
|
1163
|
+
image_accessor :preview_image do
|
1164
|
+
what :now?
|
1165
|
+
end
|
1166
|
+
end
|
1167
|
+
}.should raise_error(NoMethodError)
|
1168
|
+
end
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
describe "changed?" do
|
1172
|
+
before(:each) do
|
1173
|
+
set_up_item_class
|
1174
|
+
@item = Item.new
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
it "should be changed when assigned" do
|
1178
|
+
@item.preview_image = 'ggg'
|
1179
|
+
@item.preview_image.should be_changed
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
it "should not be changed when saved" do
|
1183
|
+
@item.preview_image = 'ggg'
|
1184
|
+
@item.save!
|
1185
|
+
@item.preview_image.should_not be_changed
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
it "should not be changed when reloaded" do
|
1189
|
+
@item.preview_image = 'ggg'
|
1190
|
+
@item.save!
|
1191
|
+
item = Item.find(@item.id)
|
1192
|
+
item.preview_image.should_not be_changed
|
1193
|
+
end
|
1194
|
+
end
|
1195
|
+
|
1196
|
+
describe "retain and pending" do
|
1197
|
+
before(:each) do
|
1198
|
+
set_up_item_class(@app=test_app)
|
1199
|
+
@app.analyser.add :some_analyser_method do |temp_object|
|
1200
|
+
temp_object.data.upcase
|
1201
|
+
end
|
1202
|
+
@item = Item.new
|
1203
|
+
end
|
1204
|
+
|
1205
|
+
it "should return nil if there are no changes" do
|
1206
|
+
@item.retained_preview_image.should be_nil
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
it "should return nil if assigned but not saved" do
|
1210
|
+
@item.preview_image = 'hello'
|
1211
|
+
@item.retained_preview_image.should be_nil
|
1212
|
+
end
|
1213
|
+
|
1214
|
+
it "should return nil if assigned and saved" do
|
1215
|
+
@item.preview_image = 'hello'
|
1216
|
+
@item.save!
|
1217
|
+
@item.retained_preview_image.should be_nil
|
1218
|
+
end
|
1219
|
+
|
1220
|
+
it "should return the saved stuff if assigned and retained" do
|
1221
|
+
@item.preview_image = 'hello'
|
1222
|
+
@item.preview_image.name = 'dog.biscuit'
|
1223
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data('hello'), anything).and_return('new/uid')
|
1224
|
+
@item.preview_image.retain!
|
1225
|
+
Dragonfly::Serializer.marshal_decode(@item.retained_preview_image).should == {
|
1226
|
+
:uid => 'new/uid',
|
1227
|
+
:some_analyser_method => 'HELLO',
|
1228
|
+
:size => 5,
|
1229
|
+
:name => 'dog.biscuit'
|
1230
|
+
}
|
1231
|
+
end
|
1232
|
+
|
1233
|
+
it "should return nil if assigned, retained and saved" do
|
1234
|
+
@item.preview_image = 'hello'
|
1235
|
+
@item.preview_image.retain!
|
1236
|
+
@item.save!
|
1237
|
+
@item.retained_preview_image.should be_nil
|
1238
|
+
end
|
1239
|
+
|
1240
|
+
it "should return nil if assigned, saved and retained" do
|
1241
|
+
@item.preview_image = 'hello'
|
1242
|
+
@item.save!
|
1243
|
+
@item.preview_image.retain!
|
1244
|
+
@item.retained_preview_image.should be_nil
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
it "should return nil if no changes have been made" do
|
1248
|
+
@item.preview_image = 'hello'
|
1249
|
+
@item.save!
|
1250
|
+
item = Item.find(@item.id)
|
1251
|
+
item.preview_image.retain!
|
1252
|
+
item.retained_preview_image.should be_nil
|
1253
|
+
end
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
describe "assigning from a pending state" do
|
1257
|
+
before(:each) do
|
1258
|
+
set_up_item_class(@app=test_app)
|
1259
|
+
@app.analyser.add :some_analyser_method do |temp_object|
|
1260
|
+
temp_object.data.upcase
|
1261
|
+
end
|
1262
|
+
@pending_string = Dragonfly::Serializer.marshal_encode(
|
1263
|
+
:uid => 'new/uid',
|
1264
|
+
:some_analyser_method => 'HELLO',
|
1265
|
+
:size => 5,
|
1266
|
+
:name => 'dog.biscuit'
|
1267
|
+
)
|
1268
|
+
@item = Item.new
|
1269
|
+
end
|
1270
|
+
|
1271
|
+
it "should update the attributes" do
|
1272
|
+
@item.retained_preview_image = @pending_string
|
1273
|
+
@item.preview_image_uid.should == 'new/uid'
|
1274
|
+
@item.preview_image_some_analyser_method.should == 'HELLO'
|
1275
|
+
@item.preview_image_size.should == 5
|
1276
|
+
@item.preview_image_name.should == 'dog.biscuit'
|
1277
|
+
end
|
1278
|
+
|
1279
|
+
it "should update the attachment meta" do
|
1280
|
+
@item.retained_preview_image = @pending_string
|
1281
|
+
@item.preview_image.meta[:some_analyser_method].should == 'HELLO'
|
1282
|
+
@item.preview_image.meta[:size].should == 5
|
1283
|
+
@item.preview_image.meta[:name].should == 'dog.biscuit'
|
1284
|
+
end
|
1285
|
+
|
1286
|
+
it "should be a normal fetch job" do
|
1287
|
+
@item.retained_preview_image = @pending_string
|
1288
|
+
@app.datastore.should_receive(:retrieve).with('new/uid').and_return(Dragonfly::TempObject.new('retrieved yo'))
|
1289
|
+
@item.preview_image.data.should == 'retrieved yo'
|
1290
|
+
end
|
1291
|
+
|
1292
|
+
it "should give the correct url" do
|
1293
|
+
@item.retained_preview_image = @pending_string
|
1294
|
+
@item.preview_image.url.should =~ %r{^/\w+/dog.biscuit$}
|
1295
|
+
end
|
1296
|
+
|
1297
|
+
it "should raise an error if the pending string contains a non-magic attr method" do
|
1298
|
+
pending_string = Dragonfly::Serializer.marshal_encode(
|
1299
|
+
:uid => 'new/uid',
|
1300
|
+
:some_analyser_method => 'HELLO',
|
1301
|
+
:size => 5,
|
1302
|
+
:name => 'dog.biscuit',
|
1303
|
+
:something => 'else'
|
1304
|
+
)
|
1305
|
+
item = @item
|
1306
|
+
lambda{
|
1307
|
+
item.retained_preview_image = pending_string
|
1308
|
+
}.should raise_error(Dragonfly::ActiveModelExtensions::Attachment::BadAssignmentKey)
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
[nil, "", "asdfsad"].each do |value|
|
1312
|
+
it "should do nothing if assigned with #{value}" do
|
1313
|
+
@item.retained_preview_image = value
|
1314
|
+
@item.preview_image_uid.should be_nil
|
1315
|
+
end
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
it "should return the pending string again" do
|
1319
|
+
@item.retained_preview_image = @pending_string
|
1320
|
+
Dragonfly::Serializer.marshal_decode(@item.retained_preview_image).should ==
|
1321
|
+
Dragonfly::Serializer.marshal_decode(@pending_string)
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
it "should destroy the old one on save" do
|
1325
|
+
@item.preview_image = 'oldone'
|
1326
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data('oldone'), anything).and_return('old/uid')
|
1327
|
+
@item.save!
|
1328
|
+
item = Item.find(@item.id)
|
1329
|
+
item.retained_preview_image = @pending_string
|
1330
|
+
@app.datastore.should_receive(:destroy).with('old/uid')
|
1331
|
+
item.save!
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
describe "combinations of assignment" do
|
1335
|
+
it "should destroy the previously retained one if something new is then assigned" do
|
1336
|
+
@item.retained_preview_image = @pending_string
|
1337
|
+
@app.datastore.should_receive(:destroy).with('new/uid')
|
1338
|
+
@item.preview_image = 'yet another new thing'
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
it "should destroy the previously retained one if something new is already assigned" do
|
1342
|
+
@item.preview_image = 'yet another new thing'
|
1343
|
+
@app.datastore.should_receive(:destroy).with('new/uid')
|
1344
|
+
@item.retained_preview_image = @pending_string
|
1345
|
+
end
|
1346
|
+
|
1347
|
+
it "should destroy the previously retained one if nil is then assigned" do
|
1348
|
+
@item.retained_preview_image = @pending_string
|
1349
|
+
@app.datastore.should_receive(:destroy).with('new/uid')
|
1350
|
+
@item.preview_image = nil
|
1351
|
+
end
|
1352
|
+
|
1353
|
+
it "should destroy the previously retained one if nil is already assigned" do
|
1354
|
+
@item.preview_image = nil
|
1355
|
+
@app.datastore.should_receive(:destroy).with('new/uid')
|
1356
|
+
@item.retained_preview_image = @pending_string
|
1357
|
+
end
|
1358
|
+
|
1359
|
+
describe "automatically retaining (hack to test for existence of hidden form field)" do
|
1360
|
+
it "should automatically retain if set as an empty string then changed" do
|
1361
|
+
@item.retained_preview_image = ""
|
1362
|
+
@item.dragonfly_attachments[:preview_image].should_receive(:retain!)
|
1363
|
+
@item.preview_image = "hello"
|
1364
|
+
end
|
1365
|
+
|
1366
|
+
it "should automatically retain if changed then set as an empty string" do
|
1367
|
+
@item.preview_image = "hello"
|
1368
|
+
@item.preview_image.should_receive(:retain!)
|
1369
|
+
@item.retained_preview_image = ""
|
1370
|
+
end
|
1371
|
+
|
1372
|
+
it "should retain if retained_string then accessor is assigned" do
|
1373
|
+
@item.retained_preview_image = @pending_string
|
1374
|
+
@item.preview_image.should_receive(:retain!)
|
1375
|
+
@item.preview_image = 'yet another new thing'
|
1376
|
+
end
|
1377
|
+
|
1378
|
+
it "should retain if accessor then retained_string is assigned" do
|
1379
|
+
@item.preview_image = 'yet another new thing'
|
1380
|
+
@item.preview_image.should_receive(:retain!)
|
1381
|
+
@item.retained_preview_image = @pending_string
|
1382
|
+
end
|
1383
|
+
end
|
1384
|
+
end
|
1385
|
+
|
1386
|
+
end
|
1387
|
+
|
1388
|
+
describe "format and mime type" do
|
1389
|
+
before(:each) do
|
1390
|
+
@app = test_app
|
1391
|
+
@app.analyser.add :mime_type do |temp_object|
|
1392
|
+
'some/type'
|
1393
|
+
end
|
1394
|
+
set_up_item_class(@app)
|
1395
|
+
@item = Item.new
|
1396
|
+
@content = "doggo"
|
1397
|
+
@content.stub!(:original_filename).and_return('egg.png')
|
1398
|
+
end
|
1399
|
+
it "should trust the file extension with format if configured to" do
|
1400
|
+
@item.preview_image = @content
|
1401
|
+
@item.preview_image.format.should == :png
|
1402
|
+
end
|
1403
|
+
it "should trust the file extension with mime_type if configured to" do
|
1404
|
+
@item.preview_image = @content
|
1405
|
+
@item.preview_image.mime_type.should == 'image/png'
|
1406
|
+
end
|
1407
|
+
it "should not trust the file extension with format if configured not to" do
|
1408
|
+
@app.trust_file_extensions = false
|
1409
|
+
@item.preview_image = @content
|
1410
|
+
@item.preview_image.format.should == nil
|
1411
|
+
end
|
1412
|
+
it "should not trust the file extension with mime_type if configured not to" do
|
1413
|
+
@app.trust_file_extensions = false
|
1414
|
+
@item.preview_image = @content
|
1415
|
+
@item.preview_image.mime_type.should == 'some/type'
|
1416
|
+
end
|
1417
|
+
end
|
1418
|
+
|
1419
|
+
describe "inspect" do
|
1420
|
+
before(:each) do
|
1421
|
+
set_up_item_class
|
1422
|
+
@item = Item.new :preview_image => 'blug'
|
1423
|
+
@item.save!
|
1424
|
+
end
|
1425
|
+
it "should be awesome" do
|
1426
|
+
@item.preview_image.inspect.should =~ %r{^<Dragonfly Attachment uid="[^"]+".*>$}
|
1427
|
+
end
|
1428
|
+
end
|
1429
|
+
|
1430
|
+
end
|