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.
- data/.specopts +2 -0
- data/.yardopts +23 -0
- data/Gemfile +23 -0
- data/Gemfile.rails.2.3.5 +14 -0
- data/History.md +266 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +92 -0
- data/VERSION +1 -0
- data/config.ru +13 -0
- data/docs.watchr +1 -0
- data/dragonfly.gemspec +293 -0
- data/extra_docs/Analysers.md +108 -0
- data/extra_docs/Caching.md +23 -0
- data/extra_docs/Configuration.md +138 -0
- data/extra_docs/DataStorage.md +136 -0
- data/extra_docs/Encoding.md +96 -0
- data/extra_docs/GeneralUsage.md +121 -0
- data/extra_docs/Generators.md +102 -0
- data/extra_docs/Heroku.md +50 -0
- data/extra_docs/Index.md +36 -0
- data/extra_docs/MimeTypes.md +40 -0
- data/extra_docs/Models.md +266 -0
- data/extra_docs/Mongo.md +45 -0
- data/extra_docs/Processing.md +130 -0
- data/extra_docs/Rack.md +52 -0
- data/extra_docs/Rails2.md +55 -0
- data/extra_docs/Rails3.md +62 -0
- data/extra_docs/Sinatra.md +25 -0
- data/extra_docs/URLs.md +169 -0
- data/features/3.0.3.feature +8 -0
- data/features/images.feature +47 -0
- data/features/no_processing.feature +14 -0
- data/features/rails_2.3.5.feature +7 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +66 -0
- data/features/steps/rails_steps.rb +39 -0
- data/features/support/env.rb +40 -0
- data/fixtures/files/app/models/album.rb +3 -0
- data/fixtures/files/app/views/albums/new.html.erb +4 -0
- data/fixtures/files/app/views/albums/show.html.erb +4 -0
- data/fixtures/files/config/initializers/dragonfly.rb +4 -0
- data/fixtures/files/features/manage_album_images.feature +12 -0
- data/fixtures/files/features/step_definitions/image_steps.rb +15 -0
- data/fixtures/files/features/support/paths.rb +15 -0
- data/fixtures/files/features/text_images.feature +7 -0
- data/fixtures/rails_2.3.5/template.rb +10 -0
- data/fixtures/rails_3.0.3/template.rb +20 -0
- data/irbrc.rb +17 -0
- data/lib/dragonfly.rb +45 -0
- data/lib/dragonfly/active_model_extensions.rb +13 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +169 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +45 -0
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_model_extensions/validations.rb +37 -0
- data/lib/dragonfly/analyser.rb +59 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
- data/lib/dragonfly/analysis/image_magick_analyser.rb +47 -0
- data/lib/dragonfly/analysis/r_magick_analyser.rb +63 -0
- data/lib/dragonfly/app.rb +182 -0
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/image_magick.rb +41 -0
- data/lib/dragonfly/config/r_magick.rb +46 -0
- data/lib/dragonfly/config/rails.rb +17 -0
- data/lib/dragonfly/configurable.rb +119 -0
- data/lib/dragonfly/core_ext/object.rb +8 -0
- data/lib/dragonfly/core_ext/string.rb +9 -0
- data/lib/dragonfly/core_ext/symbol.rb +9 -0
- data/lib/dragonfly/data_storage.rb +9 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +114 -0
- data/lib/dragonfly/data_storage/mongo_data_store.rb +82 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +115 -0
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/image_magick_encoder.rb +57 -0
- data/lib/dragonfly/encoding/r_magick_encoder.rb +61 -0
- data/lib/dragonfly/function_manager.rb +69 -0
- data/lib/dragonfly/generation/hash_with_css_style_keys.rb +23 -0
- data/lib/dragonfly/generation/image_magick_generator.rb +140 -0
- data/lib/dragonfly/generation/r_magick_generator.rb +155 -0
- data/lib/dragonfly/generator.rb +9 -0
- data/lib/dragonfly/image_magick_utils.rb +81 -0
- data/lib/dragonfly/job.rb +371 -0
- data/lib/dragonfly/job_builder.rb +39 -0
- data/lib/dragonfly/job_definitions.rb +26 -0
- data/lib/dragonfly/job_endpoint.rb +15 -0
- data/lib/dragonfly/loggable.rb +28 -0
- data/lib/dragonfly/middleware.rb +34 -0
- data/lib/dragonfly/processing/image_magick_processor.rb +99 -0
- data/lib/dragonfly/processing/r_magick_processor.rb +126 -0
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/r_magick_utils.rb +48 -0
- data/lib/dragonfly/rails/images.rb +22 -0
- data/lib/dragonfly/response.rb +82 -0
- data/lib/dragonfly/routed_endpoint.rb +40 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/simple_endpoint.rb +63 -0
- data/lib/dragonfly/temp_object.rb +220 -0
- data/samples/beach.png +0 -0
- data/samples/egg.png +0 -0
- data/samples/round.gif +0 -0
- data/samples/sample.docx +0 -0
- data/samples/taj.jpg +0 -0
- data/spec/argument_matchers.rb +19 -0
- data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
- data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
- data/spec/dragonfly/active_model_extensions/model_spec.rb +723 -0
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
- data/spec/dragonfly/analyser_spec.rb +123 -0
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +57 -0
- data/spec/dragonfly/analysis/image_magick_analyser_spec.rb +15 -0
- data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +27 -0
- data/spec/dragonfly/analysis/shared_analyser_spec.rb +51 -0
- data/spec/dragonfly/app_spec.rb +280 -0
- data/spec/dragonfly/config/r_magick_spec.rb +25 -0
- data/spec/dragonfly/configurable_spec.rb +220 -0
- data/spec/dragonfly/core_ext/string_spec.rb +17 -0
- data/spec/dragonfly/core_ext/symbol_spec.rb +17 -0
- data/spec/dragonfly/data_storage/data_store_spec.rb +76 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +169 -0
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +38 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +94 -0
- data/spec/dragonfly/deprecation_spec.rb +20 -0
- data/spec/dragonfly/encoding/image_magick_encoder_spec.rb +41 -0
- data/spec/dragonfly/encoding/r_magick_encoder_spec.rb +37 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/generation/hash_with_css_style_keys_spec.rb +24 -0
- data/spec/dragonfly/generation/image_magick_generator_spec.rb +12 -0
- data/spec/dragonfly/generation/r_magick_generator_spec.rb +24 -0
- data/spec/dragonfly/generation/shared_generator_spec.rb +91 -0
- data/spec/dragonfly/image_magick_utils_spec.rb +16 -0
- data/spec/dragonfly/job_builder_spec.rb +37 -0
- data/spec/dragonfly/job_definitions_spec.rb +35 -0
- data/spec/dragonfly/job_endpoint_spec.rb +120 -0
- data/spec/dragonfly/job_spec.rb +773 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +68 -0
- data/spec/dragonfly/processing/image_magick_processor_spec.rb +29 -0
- data/spec/dragonfly/processing/r_magick_processor_spec.rb +26 -0
- data/spec/dragonfly/processing/shared_processing_spec.rb +215 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
- data/spec/dragonfly/serializer_spec.rb +61 -0
- data/spec/dragonfly/simple_cache_spec.rb +27 -0
- data/spec/dragonfly/simple_endpoint_spec.rb +89 -0
- data/spec/dragonfly/temp_object_spec.rb +352 -0
- data/spec/image_matchers.rb +47 -0
- data/spec/simple_matchers.rb +44 -0
- data/spec/spec_helper.rb +58 -0
- data/yard/handlers/configurable_attr_handler.rb +38 -0
- data/yard/setup.rb +15 -0
- data/yard/templates/default/fulldoc/html/css/common.css +107 -0
- data/yard/templates/default/layout/html/layout.erb +87 -0
- data/yard/templates/default/module/html/configuration_summary.erb +31 -0
- data/yard/templates/default/module/setup.rb +17 -0
- metadata +550 -0
data/samples/beach.png
ADDED
|
Binary file
|
data/samples/egg.png
ADDED
|
Binary file
|
data/samples/round.gif
ADDED
|
Binary file
|
data/samples/sample.docx
ADDED
|
Binary file
|
data/samples/taj.jpg
ADDED
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
def string_matching(regexp)
|
|
2
|
+
Spec::Mocks::ArgumentMatchers::RegexpMatcher.new(regexp)
|
|
3
|
+
end
|
|
4
|
+
|
|
5
|
+
class TempObjectArgumentMatcher
|
|
6
|
+
def initialize(data, opts)
|
|
7
|
+
@data = data
|
|
8
|
+
@opts = opts
|
|
9
|
+
end
|
|
10
|
+
def ==(actual)
|
|
11
|
+
actual.is_a?(Dragonfly::TempObject) &&
|
|
12
|
+
actual.data == @data &&
|
|
13
|
+
@opts.all?{|k,v| actual.send(k) == v }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def a_temp_object_with_data(data, opts={})
|
|
18
|
+
TempObjectArgumentMatcher.new(data, opts)
|
|
19
|
+
end
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# --------------------------------------------------------------- #
|
|
2
|
+
# MODELS
|
|
3
|
+
# --------------------------------------------------------------- #
|
|
4
|
+
class MyModel
|
|
5
|
+
|
|
6
|
+
# Callbacks
|
|
7
|
+
extend ActiveModel::Callbacks
|
|
8
|
+
define_model_callbacks :save, :destroy
|
|
9
|
+
|
|
10
|
+
include ActiveModel::Validations
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def create!(attrs={})
|
|
14
|
+
new(attrs).save!
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def find(id)
|
|
18
|
+
new(instances[id])
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def instances
|
|
22
|
+
@instances ||= {}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def initialize(attrs={})
|
|
27
|
+
attrs.each do |key, value|
|
|
28
|
+
send("#{key}=", value)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
attr_accessor :id
|
|
33
|
+
|
|
34
|
+
def to_hash
|
|
35
|
+
self.class::ATTRIBUTES.inject({}) do |hash, attr|
|
|
36
|
+
hash[attr] = send(attr)
|
|
37
|
+
hash
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def save
|
|
42
|
+
_run_save_callbacks {
|
|
43
|
+
self.id ||= rand(1000)
|
|
44
|
+
self.class.instances[id] = self.to_hash
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
def save!
|
|
48
|
+
save
|
|
49
|
+
self
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def destroy
|
|
53
|
+
_run_destroy_callbacks {}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
class Item < MyModel
|
|
58
|
+
|
|
59
|
+
ATTRIBUTES = [
|
|
60
|
+
:title,
|
|
61
|
+
:preview_image_uid,
|
|
62
|
+
:preview_image_some_analyser_method,
|
|
63
|
+
:preview_image_size,
|
|
64
|
+
:preview_image_name,
|
|
65
|
+
:preview_image_ext,
|
|
66
|
+
:preview_image_blah_blah,
|
|
67
|
+
:other_image_uid,
|
|
68
|
+
:yet_another_image_uid,
|
|
69
|
+
:otra_imagen_uid,
|
|
70
|
+
:trailer_video_uid,
|
|
71
|
+
:created_at,
|
|
72
|
+
:updated_at
|
|
73
|
+
]
|
|
74
|
+
attr_accessor *ATTRIBUTES
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class Car < MyModel
|
|
78
|
+
ATTRIBUTES = [
|
|
79
|
+
:image_uid,
|
|
80
|
+
:reliant_image_uid,
|
|
81
|
+
:type
|
|
82
|
+
]
|
|
83
|
+
attr_accessor *ATTRIBUTES
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
class Photo < MyModel
|
|
87
|
+
ATTRIBUTES = [:image_uid]
|
|
88
|
+
attr_accessor *ATTRIBUTES
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# --------------------------------------------------------------- #
|
|
93
|
+
# HELPER METHODS
|
|
94
|
+
# --------------------------------------------------------------- #
|
|
95
|
+
def model_class
|
|
96
|
+
MyModel
|
|
97
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Seems to blow up on Rails 3 without this - only need temporarily
|
|
2
|
+
begin
|
|
3
|
+
require 'active_support/all'
|
|
4
|
+
rescue LoadError => e
|
|
5
|
+
puts "Couldn't load activesupport: #{e}"
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
require 'active_record'
|
|
9
|
+
|
|
10
|
+
# --------------------------------------------------------------- #
|
|
11
|
+
# MIGRATION
|
|
12
|
+
# --------------------------------------------------------------- #
|
|
13
|
+
class MigrationForTest < ActiveRecord::Migration
|
|
14
|
+
|
|
15
|
+
def self.up
|
|
16
|
+
create_table :items, :force => true do |t|
|
|
17
|
+
t.string :title
|
|
18
|
+
t.string :preview_image_uid
|
|
19
|
+
t.string :preview_image_some_analyser_method
|
|
20
|
+
t.integer :preview_image_size
|
|
21
|
+
t.string :preview_image_name
|
|
22
|
+
t.string :preview_image_ext
|
|
23
|
+
t.string :preview_image_blah_blah
|
|
24
|
+
t.string :other_image_uid
|
|
25
|
+
t.string :yet_another_image_uid
|
|
26
|
+
t.string :otra_imagen_uid
|
|
27
|
+
t.string :trailer_video_uid
|
|
28
|
+
t.timestamps
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
create_table :cars do |t|
|
|
32
|
+
t.string :image_uid
|
|
33
|
+
t.string :reliant_image_uid
|
|
34
|
+
t.string :type
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
create_table :photos do |t|
|
|
38
|
+
t.string :image_uid
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.down
|
|
44
|
+
drop_table :items
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# --------------------------------------------------------------- #
|
|
51
|
+
# MODELS
|
|
52
|
+
# --------------------------------------------------------------- #
|
|
53
|
+
class Item < ActiveRecord::Base
|
|
54
|
+
end
|
|
55
|
+
class Car < ActiveRecord::Base
|
|
56
|
+
end
|
|
57
|
+
class Photo < ActiveRecord::Base
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# --------------------------------------------------------------- #
|
|
62
|
+
# SPEC CONFIG
|
|
63
|
+
# --------------------------------------------------------------- #
|
|
64
|
+
DB_FILE = File.expand_path(File.dirname(__FILE__)+'/db.sqlite3')
|
|
65
|
+
|
|
66
|
+
Spec::Runner.configure do |config|
|
|
67
|
+
|
|
68
|
+
config.before(:all) do
|
|
69
|
+
FileUtils.rm_f(DB_FILE)
|
|
70
|
+
ActiveRecord::Base.establish_connection(
|
|
71
|
+
:adapter => "sqlite3",
|
|
72
|
+
:database => DB_FILE
|
|
73
|
+
)
|
|
74
|
+
MigrationForTest.verbose = false
|
|
75
|
+
MigrationForTest.up
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# --------------------------------------------------------------- #
|
|
81
|
+
# HELPER METHODS
|
|
82
|
+
# --------------------------------------------------------------- #
|
|
83
|
+
def model_class
|
|
84
|
+
ActiveRecord::Base
|
|
85
|
+
end
|
|
@@ -0,0 +1,723 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Item do
|
|
4
|
+
|
|
5
|
+
# See extra setup in models / initializer files
|
|
6
|
+
|
|
7
|
+
describe "defining accessors" do
|
|
8
|
+
|
|
9
|
+
let(:app1){ Dragonfly[:images] }
|
|
10
|
+
let(:app2){ Dragonfly[:videos] }
|
|
11
|
+
|
|
12
|
+
it "should return the mapping of apps to attributes" do
|
|
13
|
+
app1.define_macro(model_class, :image_accessor)
|
|
14
|
+
app2.define_macro(model_class, :video_accessor)
|
|
15
|
+
Item.class_eval do
|
|
16
|
+
image_accessor :preview_image
|
|
17
|
+
video_accessor :trailer_video
|
|
18
|
+
end
|
|
19
|
+
Item.dragonfly_apps_for_attributes.should == {:preview_image => app1, :trailer_video => app2}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should work for included modules (e.g. Mongoid::Document)" do
|
|
23
|
+
mongoid_document = Module.new
|
|
24
|
+
app1.define_macro_on_include(mongoid_document, :dog_accessor)
|
|
25
|
+
model_class = Class.new do
|
|
26
|
+
def self.before_save(*args); end
|
|
27
|
+
def self.before_destroy(*args); end
|
|
28
|
+
include mongoid_document
|
|
29
|
+
dog_accessor :doogie
|
|
30
|
+
end
|
|
31
|
+
model_class.dragonfly_apps_for_attributes.should == {:doogie => app1}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "correctly defined" do
|
|
37
|
+
|
|
38
|
+
before(:each) do
|
|
39
|
+
@app = Dragonfly[:images]
|
|
40
|
+
@app.define_macro(model_class, :image_accessor)
|
|
41
|
+
Item.class_eval do
|
|
42
|
+
image_accessor :preview_image
|
|
43
|
+
end
|
|
44
|
+
@item = Item.new
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should provide a reader" do
|
|
48
|
+
@item.should respond_to(:preview_image)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should provide a writer" do
|
|
52
|
+
@item.should respond_to(:preview_image=)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe "when there has been nothing assigned" do
|
|
56
|
+
it "the reader should return nil" do
|
|
57
|
+
@item.preview_image.should be_nil
|
|
58
|
+
end
|
|
59
|
+
it "the uid should be nil" do
|
|
60
|
+
@item.preview_image_uid.should be_nil
|
|
61
|
+
end
|
|
62
|
+
it "should not try to store anything on save" do
|
|
63
|
+
@app.datastore.should_not_receive(:store)
|
|
64
|
+
@item.save!
|
|
65
|
+
end
|
|
66
|
+
it "should not try to destroy anything on save" do
|
|
67
|
+
@app.datastore.should_not_receive(:destroy)
|
|
68
|
+
@item.save!
|
|
69
|
+
end
|
|
70
|
+
it "should not try to destroy anything on destroy" do
|
|
71
|
+
@app.datastore.should_not_receive(:destroy)
|
|
72
|
+
@item.destroy
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
describe "when the uid is set manually" do
|
|
77
|
+
before(:each) do
|
|
78
|
+
@item.preview_image_uid = 'some_known_uid'
|
|
79
|
+
end
|
|
80
|
+
it "should not try to retrieve any data" do
|
|
81
|
+
@app.datastore.should_not_receive(:retrieve)
|
|
82
|
+
@item.save!
|
|
83
|
+
end
|
|
84
|
+
it "should not try to destroy any data" do
|
|
85
|
+
@app.datastore.should_not_receive(:destroy)
|
|
86
|
+
@item.save!
|
|
87
|
+
end
|
|
88
|
+
it "should not try to store any data" do
|
|
89
|
+
@app.datastore.should_not_receive(:store)
|
|
90
|
+
@item.save!
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe "when there has been some thing assigned but not saved" do
|
|
95
|
+
before(:each) do
|
|
96
|
+
@item.preview_image = "DATASTRING"
|
|
97
|
+
end
|
|
98
|
+
it "the reader should return an attachment" do
|
|
99
|
+
@item.preview_image.should be_a(Dragonfly::ActiveModelExtensions::Attachment)
|
|
100
|
+
end
|
|
101
|
+
it "the uid should be nil" do
|
|
102
|
+
@item.preview_image_uid.should be_nil
|
|
103
|
+
end
|
|
104
|
+
it "should store the image when saved" do
|
|
105
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"), {})
|
|
106
|
+
@item.save!
|
|
107
|
+
end
|
|
108
|
+
it "should not try to destroy anything on destroy" do
|
|
109
|
+
@app.datastore.should_not_receive(:destroy)
|
|
110
|
+
@item.destroy
|
|
111
|
+
end
|
|
112
|
+
it "should return nil for the url" do
|
|
113
|
+
@item.preview_image.url.should be_nil
|
|
114
|
+
end
|
|
115
|
+
describe "when the uid is set manually" do
|
|
116
|
+
before(:each) do
|
|
117
|
+
@item.preview_image_uid = 'some_known_uid'
|
|
118
|
+
end
|
|
119
|
+
it "should not try to retrieve any data" do
|
|
120
|
+
@app.datastore.should_not_receive(:retrieve)
|
|
121
|
+
@item.save!
|
|
122
|
+
end
|
|
123
|
+
it "should not try to destroy any data" do
|
|
124
|
+
@app.datastore.should_not_receive(:destroy)
|
|
125
|
+
@item.save!
|
|
126
|
+
end
|
|
127
|
+
it "should not try to store any data" do
|
|
128
|
+
@app.datastore.should_not_receive(:store)
|
|
129
|
+
@item.save!
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
describe "when something has been assigned and saved" do
|
|
136
|
+
|
|
137
|
+
before(:each) do
|
|
138
|
+
@item.preview_image = "DATASTRING"
|
|
139
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"), {}).once.and_return('some_uid')
|
|
140
|
+
@item.save!
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "should have the correct uid" do
|
|
144
|
+
@item.preview_image_uid.should == 'some_uid'
|
|
145
|
+
end
|
|
146
|
+
it "should not try to store anything if saved again" do
|
|
147
|
+
@app.datastore.should_not_receive(:store)
|
|
148
|
+
@item.save!
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "should not try to destroy anything if saved again" do
|
|
152
|
+
@app.datastore.should_not_receive(:destroy)
|
|
153
|
+
@item.save!
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it "should destroy the data on destroy" do
|
|
157
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
158
|
+
@item.destroy
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "should return the url for the data" do
|
|
162
|
+
@app.should_receive(:url_for).with(an_instance_of(Dragonfly::Job)).and_return('some.url')
|
|
163
|
+
@item.preview_image.url.should == 'some.url'
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "should destroy the old data when the uid is set manually" do
|
|
167
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
168
|
+
@item.preview_image_uid = 'some_known_uid'
|
|
169
|
+
@item.save!
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe "when accessed by a new model object" do
|
|
173
|
+
before(:each) do
|
|
174
|
+
@item = Item.find(@item.id)
|
|
175
|
+
end
|
|
176
|
+
it "should destroy the data on destroy" do
|
|
177
|
+
@app.datastore.should_receive(:destroy).with(@item.preview_image_uid)
|
|
178
|
+
@item.destroy
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe "when something new is assigned" do
|
|
183
|
+
before(:each) do
|
|
184
|
+
@item.preview_image = "ANEWDATASTRING"
|
|
185
|
+
@app.datastore.stub!(:store).and_return('some_uid')
|
|
186
|
+
end
|
|
187
|
+
it "should set the uid to nil" do
|
|
188
|
+
@item.preview_image_uid.should be_nil
|
|
189
|
+
end
|
|
190
|
+
it "should destroy the old data when saved" do
|
|
191
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
192
|
+
@item.save!
|
|
193
|
+
end
|
|
194
|
+
it "should not try to destroy the old data if saved again" do
|
|
195
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
196
|
+
@item.save!
|
|
197
|
+
@app.datastore.should_not_receive(:destroy).with('some_uid')
|
|
198
|
+
@item.save!
|
|
199
|
+
end
|
|
200
|
+
it "should destroy the old data when saved, even if yet another thing is assigned" do
|
|
201
|
+
@item.preview_image = "YET ANOTHER DATA STRING"
|
|
202
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
203
|
+
@item.save!
|
|
204
|
+
end
|
|
205
|
+
it "should store the new data when saved" do
|
|
206
|
+
@app.datastore.should_receive(:store).with(a_temp_object_with_data("ANEWDATASTRING"), {})
|
|
207
|
+
@item.save!
|
|
208
|
+
end
|
|
209
|
+
it "should destroy the old data on destroy" do
|
|
210
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
211
|
+
@item.destroy
|
|
212
|
+
end
|
|
213
|
+
it "should destroy the old data on destroy, even if yet another thing is assigned" do
|
|
214
|
+
@item.preview_image = "YET ANOTHER DATA STRING"
|
|
215
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
216
|
+
@item.destroy
|
|
217
|
+
end
|
|
218
|
+
it "should destroy the old data when the uid has been set manually" do
|
|
219
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
220
|
+
@item.preview_image_uid = 'some_known_uid'
|
|
221
|
+
@item.save!
|
|
222
|
+
end
|
|
223
|
+
it "should return the new size" do
|
|
224
|
+
@item.preview_image.size.should == 14
|
|
225
|
+
end
|
|
226
|
+
it "should return the new data" do
|
|
227
|
+
@item.preview_image.data.should == 'ANEWDATASTRING'
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
describe "when it is set to nil" do
|
|
232
|
+
before(:each) do
|
|
233
|
+
@item.preview_image = nil
|
|
234
|
+
end
|
|
235
|
+
it "should set the uid to nil" do
|
|
236
|
+
@item.preview_image_uid.should be_nil
|
|
237
|
+
end
|
|
238
|
+
it "should return the attribute as nil" do
|
|
239
|
+
@item.preview_image.should be_nil
|
|
240
|
+
end
|
|
241
|
+
it "should destroy the data on save" do
|
|
242
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
243
|
+
@item.save!
|
|
244
|
+
@item.preview_image.should be_nil
|
|
245
|
+
end
|
|
246
|
+
it "should destroy the old data on destroy" do
|
|
247
|
+
@app.datastore.should_receive(:destroy).with('some_uid')
|
|
248
|
+
@item.destroy
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
describe "when the data can't be found" do
|
|
253
|
+
it "should log a warning if the data wasn't found on destroy" do
|
|
254
|
+
@app.datastore.should_receive(:destroy).with('some_uid').and_raise(Dragonfly::DataStorage::DataNotFound)
|
|
255
|
+
@app.log.should_receive(:warn)
|
|
256
|
+
@item.destroy
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
describe "other types of assignment" do
|
|
263
|
+
before(:each) do
|
|
264
|
+
@app.generator.add :egg do
|
|
265
|
+
"Gungedin"
|
|
266
|
+
end
|
|
267
|
+
@app.processor.add :doogie do |temp_object|
|
|
268
|
+
temp_object.data.upcase
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
describe "assigning with a job" do
|
|
273
|
+
before(:each) do
|
|
274
|
+
@job = @app.generate(:egg)
|
|
275
|
+
@item.preview_image = @job
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
it "should work" do
|
|
279
|
+
@item.preview_image.data.should == 'Gungedin'
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it "should not be affected by subsequent changes to the job" do
|
|
283
|
+
@job.process!(:doogie)
|
|
284
|
+
@item.preview_image.data.should == 'Gungedin'
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
describe "assigning with another attachment" do
|
|
289
|
+
before(:each) do
|
|
290
|
+
Item.class_eval do
|
|
291
|
+
image_accessor :other_image
|
|
292
|
+
end
|
|
293
|
+
end
|
|
294
|
+
it "should work like assigning the job" do
|
|
295
|
+
@item.preview_image = 'eggheads'
|
|
296
|
+
@item.other_image = @item.preview_image
|
|
297
|
+
@item.preview_image = 'dogchin'
|
|
298
|
+
@item.other_image.data.should == 'eggheads'
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
describe "assigning by means of a bang method" do
|
|
303
|
+
before(:each) do
|
|
304
|
+
@app.processor.add :double do |temp_object|
|
|
305
|
+
temp_object.data * 2
|
|
306
|
+
end
|
|
307
|
+
@app.encoder.add do |temp_object, format|
|
|
308
|
+
temp_object.data.downcase + format.to_s
|
|
309
|
+
end
|
|
310
|
+
@item.preview_image = "HELLO"
|
|
311
|
+
end
|
|
312
|
+
it "should modify as if being assigned again" do
|
|
313
|
+
@item.preview_image.process!(:double)
|
|
314
|
+
@item.preview_image.data.should == 'HELLOHELLO'
|
|
315
|
+
end
|
|
316
|
+
it "should update the magic attributes" do
|
|
317
|
+
@item.preview_image.process!(:double)
|
|
318
|
+
@item.preview_image_size.should == 10
|
|
319
|
+
end
|
|
320
|
+
it "should work for encode" do
|
|
321
|
+
@item.preview_image.encode!(:egg)
|
|
322
|
+
@item.preview_image.data.should == 'helloegg'
|
|
323
|
+
end
|
|
324
|
+
it "should work repeatedly" do
|
|
325
|
+
@item.preview_image.process!(:double).encode!(:egg)
|
|
326
|
+
@item.preview_image.data.should == 'hellohelloegg'
|
|
327
|
+
@item.preview_image_size.should == 13
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
describe "validations" do
|
|
335
|
+
|
|
336
|
+
before(:all) do
|
|
337
|
+
@app = Dragonfly[:images]
|
|
338
|
+
@app.define_macro(model_class, :image_accessor)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
describe "validates_presence_of" do
|
|
342
|
+
|
|
343
|
+
before(:all) do
|
|
344
|
+
Item.class_eval do
|
|
345
|
+
image_accessor :preview_image
|
|
346
|
+
validates_presence_of :preview_image
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
it "should be valid if set" do
|
|
351
|
+
Item.new(:preview_image => "1234567890").should be_valid
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it "should be invalid if not set" do
|
|
355
|
+
Item.new.should_not be_valid
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
describe "validates_size_of" do
|
|
361
|
+
|
|
362
|
+
before(:all) do
|
|
363
|
+
Item.class_eval do
|
|
364
|
+
image_accessor :preview_image
|
|
365
|
+
validates_size_of :preview_image, :within => (6..10)
|
|
366
|
+
end
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it "should be valid if ok" do
|
|
370
|
+
Item.new(:preview_image => "1234567890").should be_valid
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
it "should be invalid if too small" do
|
|
374
|
+
Item.new(:preview_image => "12345").should_not be_valid
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
describe "validates_property" do
|
|
380
|
+
|
|
381
|
+
before(:each) do
|
|
382
|
+
@item = Item.new(:preview_image => "1234567890")
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
before(:all) do
|
|
386
|
+
custom_analyser = Class.new do
|
|
387
|
+
def mime_type(temp_object)
|
|
388
|
+
case temp_object.data
|
|
389
|
+
when "WRONG TYPE" then 'wrong/type'
|
|
390
|
+
when "OTHER TYPE" then nil
|
|
391
|
+
else 'how/special'
|
|
392
|
+
end
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
def number_of_Gs(temp_object)
|
|
396
|
+
temp_object.data.count('G')
|
|
397
|
+
end
|
|
398
|
+
end
|
|
399
|
+
@app.analyser.register(custom_analyser)
|
|
400
|
+
|
|
401
|
+
Item.class_eval do
|
|
402
|
+
validates_property :mime_type, :of => :preview_image, :in => ['how/special', 'how/crazy'], :if => :its_friday
|
|
403
|
+
validates_property :mime_type, :of => [:other_image, :yet_another_image], :as => 'how/special'
|
|
404
|
+
validates_property :number_of_Gs, :of => :preview_image, :in => (0..2)
|
|
405
|
+
validates_property :mime_type, :of => :otra_imagen, :in => ['que/pasa', 'illo/tio'], :message => "tipo de contenido incorrecto. Que chungo tio"
|
|
406
|
+
|
|
407
|
+
image_accessor :preview_image
|
|
408
|
+
image_accessor :other_image
|
|
409
|
+
image_accessor :yet_another_image
|
|
410
|
+
image_accessor :otra_imagen
|
|
411
|
+
|
|
412
|
+
def its_friday
|
|
413
|
+
true
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
end
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
it "should be valid if nil, if not validated on presence (even with validates_property)" do
|
|
420
|
+
@item.other_image = nil
|
|
421
|
+
@item.should be_valid
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it "should be invalid if the property is nil" do
|
|
425
|
+
@item.preview_image = "OTHER TYPE"
|
|
426
|
+
@item.should_not be_valid
|
|
427
|
+
@item.errors[:preview_image].should match_ar_error("mime type is incorrect. It needs to be one of 'how/special', 'how/crazy', but was ''")
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
it "should be invalid if the property is wrong" do
|
|
431
|
+
@item.preview_image = "WRONG TYPE"
|
|
432
|
+
@item.should_not be_valid
|
|
433
|
+
@item.errors[:preview_image].should match_ar_error("mime type is incorrect. It needs to be one of 'how/special', 'how/crazy', but was 'wrong/type'")
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
it "should work for a range" do
|
|
437
|
+
@item.preview_image = "GOOGLE GUM"
|
|
438
|
+
@item.should_not be_valid
|
|
439
|
+
@item.errors[:preview_image].should match_ar_error("number of gs is incorrect. It needs to be between 0 and 2, but was '3'")
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it "should validate individually" do
|
|
443
|
+
@item.other_image = "1234567"
|
|
444
|
+
@item.yet_another_image = "WRONG TYPE"
|
|
445
|
+
@item.should_not be_valid
|
|
446
|
+
@item.errors[:other_image].should match_ar_error(nil)
|
|
447
|
+
@item.errors[:yet_another_image].should match_ar_error("mime type is incorrect. It needs to be 'how/special', but was 'wrong/type'")
|
|
448
|
+
end
|
|
449
|
+
|
|
450
|
+
it "should include standard extra options like 'if' on mime type validation" do
|
|
451
|
+
@item.should_receive(:its_friday).and_return(false)
|
|
452
|
+
@item.preview_image = "WRONG TYPE"
|
|
453
|
+
@item.should be_valid
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
it "should require either :as or :in as an argument" do
|
|
457
|
+
lambda{
|
|
458
|
+
Item.class_eval do
|
|
459
|
+
validates_property :mime_type, :of => :preview_image
|
|
460
|
+
end
|
|
461
|
+
}.should raise_error(ArgumentError)
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
it "should require :of as an argument" do
|
|
465
|
+
lambda{
|
|
466
|
+
Item.class_eval do
|
|
467
|
+
validates_property :mime_type, :as => 'hi/there'
|
|
468
|
+
end
|
|
469
|
+
}.should raise_error(ArgumentError)
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
it "should allow for custom messages" do
|
|
473
|
+
@item.otra_imagen = "WRONG TYPE"
|
|
474
|
+
@item.should_not be_valid
|
|
475
|
+
@item.errors[:otra_imagen].should match_ar_error("tipo de contenido incorrecto. Que chungo tio")
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
describe "extra properties" do
|
|
483
|
+
|
|
484
|
+
before(:each) do
|
|
485
|
+
@app = Dragonfly[:images]
|
|
486
|
+
custom_analyser = Class.new do
|
|
487
|
+
def some_analyser_method(temp_object)
|
|
488
|
+
"abc" + temp_object.data[0..0]
|
|
489
|
+
end
|
|
490
|
+
def number_of_As(temp_object); temp_object.data.count('A'); end
|
|
491
|
+
end
|
|
492
|
+
@app.analyser.register(custom_analyser)
|
|
493
|
+
@app.define_macro(model_class, :image_accessor)
|
|
494
|
+
Item.class_eval do
|
|
495
|
+
image_accessor :preview_image
|
|
496
|
+
end
|
|
497
|
+
@item = Item.new
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
describe "magic attributes" do
|
|
501
|
+
|
|
502
|
+
it "should default the magic attribute as nil" do
|
|
503
|
+
@item.preview_image_some_analyser_method.should be_nil
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
it "should set the magic attribute when assigned" do
|
|
507
|
+
@item.preview_image = '123'
|
|
508
|
+
@item.preview_image_some_analyser_method.should == 'abc1'
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
it "should not set non-magic attributes with the same prefix when assigned" do
|
|
512
|
+
@item.preview_image_blah_blah = 'wassup'
|
|
513
|
+
@item.preview_image = '123'
|
|
514
|
+
@item.preview_image_blah_blah.should == 'wassup'
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
it "should update the magic attribute when something else is assigned" do
|
|
518
|
+
@item.preview_image = '123'
|
|
519
|
+
@item.preview_image = '456'
|
|
520
|
+
@item.preview_image_some_analyser_method.should == 'abc4'
|
|
521
|
+
end
|
|
522
|
+
|
|
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
|
+
it "should not reset non-magic attributes with the same prefix when set to nil" do
|
|
530
|
+
@item.preview_image_blah_blah = 'wassup'
|
|
531
|
+
@item.preview_image = '123'
|
|
532
|
+
@item.preview_image = nil
|
|
533
|
+
@item.preview_image_blah_blah.should == 'wassup'
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
it "should work for size too" do
|
|
537
|
+
@item.preview_image = '123'
|
|
538
|
+
@item.preview_image_size.should == 3
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
it "should store the original file extension if it exists" do
|
|
542
|
+
data = 'jasdlkf sadjl'
|
|
543
|
+
data.stub!(:original_filename).and_return('hello.png')
|
|
544
|
+
@item.preview_image = data
|
|
545
|
+
@item.preview_image_ext.should == 'png'
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
it "should store the original file name if it exists" do
|
|
549
|
+
data = 'jasdlkf sadjl'
|
|
550
|
+
data.stub!(:original_filename).and_return('hello.png')
|
|
551
|
+
@item.preview_image = data
|
|
552
|
+
@item.preview_image_name.should == 'hello.png'
|
|
553
|
+
end
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
describe "delegating methods to the job" do
|
|
558
|
+
before(:each) do
|
|
559
|
+
@item.preview_image = "DATASTRING"
|
|
560
|
+
end
|
|
561
|
+
it "should have properties from the analyser" do
|
|
562
|
+
@item.preview_image.number_of_As.should == 2
|
|
563
|
+
end
|
|
564
|
+
it "should report that it responds to analyser methods" do
|
|
565
|
+
@item.preview_image.respond_to?(:number_of_As).should be_true
|
|
566
|
+
end
|
|
567
|
+
it "should include analyser methods in methods" do
|
|
568
|
+
@item.preview_image.methods.include?('number_of_As'.to_method_name).should be_true
|
|
569
|
+
end
|
|
570
|
+
it "should include analyser methods in public_methods" do
|
|
571
|
+
@item.preview_image.public_methods.include?('number_of_As'.to_method_name).should be_true
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
it "should update when something new is assigned" do
|
|
575
|
+
@item.preview_image = 'ANEWDATASTRING'
|
|
576
|
+
@item.preview_image.number_of_As.should == 3
|
|
577
|
+
end
|
|
578
|
+
|
|
579
|
+
describe "from a new model object" do
|
|
580
|
+
before(:each) do
|
|
581
|
+
@app.datastore.stub!(:store).and_return('my_uid')
|
|
582
|
+
item = Item.create!(:preview_image => 'DATASTRING')
|
|
583
|
+
@item = Item.find(item.id)
|
|
584
|
+
end
|
|
585
|
+
it "should load the content then delegate the method" do
|
|
586
|
+
@app.datastore.should_receive(:retrieve).with('my_uid').and_return(['DATASTRING', {}])
|
|
587
|
+
@item.preview_image.number_of_As.should == 2
|
|
588
|
+
end
|
|
589
|
+
it "should use the magic attribute if there is one, and not load the content" do
|
|
590
|
+
@app.datastore.should_not_receive(:retrieve)
|
|
591
|
+
@item.should_receive(:preview_image_some_analyser_method).and_return('result yo')
|
|
592
|
+
@item.preview_image.some_analyser_method.should == 'result yo'
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
%w(size name ext).each do |attr|
|
|
596
|
+
it "should use the magic attribute for #{attr} if there is one, and not load the content" do
|
|
597
|
+
@app.datastore.should_not_receive(:retrieve)
|
|
598
|
+
@item.should_receive("preview_image_#{attr}".to_sym).and_return('result yo')
|
|
599
|
+
@item.preview_image.send(attr).should == 'result yo'
|
|
600
|
+
end
|
|
601
|
+
|
|
602
|
+
it "should load the content then delegate '#{attr}' if there is no magic attribute for it" do
|
|
603
|
+
@item.should_receive(:public_methods).and_return(['preview_image_uid']) # no magic attributes
|
|
604
|
+
@app.datastore.should_receive(:retrieve).with('my_uid').and_return(['DATASTRING', {}])
|
|
605
|
+
@item.preview_image.send(attr).should == @item.preview_image.send(:job).send(attr)
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
end
|
|
610
|
+
|
|
611
|
+
it "should not raise an error if a non-existent method is called" do
|
|
612
|
+
# Just checking method missing works ok
|
|
613
|
+
lambda{
|
|
614
|
+
@item.preview_image.eggbert
|
|
615
|
+
}.should raise_error(NoMethodError)
|
|
616
|
+
end
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
describe "setting things on the attachment" do
|
|
620
|
+
|
|
621
|
+
before(:each) do
|
|
622
|
+
@item = Item.new
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
describe "name" do
|
|
626
|
+
before(:each) do
|
|
627
|
+
@item.preview_image = "Hello"
|
|
628
|
+
@item.preview_image.name = 'hello.there'
|
|
629
|
+
end
|
|
630
|
+
it "should allow for setting the name" do
|
|
631
|
+
@item.preview_image.name.should == 'hello.there'
|
|
632
|
+
end
|
|
633
|
+
it "should update the magic attribute" do
|
|
634
|
+
@item.preview_image_name.should == 'hello.there'
|
|
635
|
+
end
|
|
636
|
+
it "should return the name" do
|
|
637
|
+
(@item.preview_image.name = 'no.silly').should == 'no.silly'
|
|
638
|
+
end
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
describe "meta" do
|
|
642
|
+
before(:each) do
|
|
643
|
+
@item.preview_image = "Hello all"
|
|
644
|
+
@item.preview_image.meta = {:slime => 'balls'}
|
|
645
|
+
end
|
|
646
|
+
it "should allow for setting the meta" do
|
|
647
|
+
@item.preview_image.meta.should == {:slime => 'balls'}
|
|
648
|
+
end
|
|
649
|
+
it "should allow for updating the meta" do
|
|
650
|
+
@item.preview_image.meta[:numb] = 'nuts'
|
|
651
|
+
@item.preview_image.meta.should == {:slime => 'balls', :numb => 'nuts'}
|
|
652
|
+
end
|
|
653
|
+
it "should return the meta" do
|
|
654
|
+
(@item.preview_image.meta = {:doogs => 'boogs'}).should == {:doogs => 'boogs'}
|
|
655
|
+
end
|
|
656
|
+
it "should save it correctly" do
|
|
657
|
+
@item.save!
|
|
658
|
+
item = Item.find(@item.id)
|
|
659
|
+
item.preview_image.meta.should include_hash(:slime => 'balls')
|
|
660
|
+
end
|
|
661
|
+
it "should store meta info about the model" do
|
|
662
|
+
@item.save!
|
|
663
|
+
meta = {:model_class => 'Item', :model_attachment => :preview_image, :slime => 'balls'}
|
|
664
|
+
@app.fetch(@item.preview_image_uid).meta.should == meta
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
describe "inheritance" do
|
|
673
|
+
|
|
674
|
+
before(:all) do
|
|
675
|
+
@app = Dragonfly[:images]
|
|
676
|
+
@app2 = Dragonfly[:egg]
|
|
677
|
+
@app.define_macro(model_class, :image_accessor)
|
|
678
|
+
@app2.define_macro(model_class, :egg_accessor)
|
|
679
|
+
Car.class_eval do
|
|
680
|
+
image_accessor :image
|
|
681
|
+
end
|
|
682
|
+
Photo.class_eval do
|
|
683
|
+
egg_accessor :image
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
@base_class = Car
|
|
687
|
+
class ReliantRobin < Car; image_accessor :reliant_image; end
|
|
688
|
+
@subclass = ReliantRobin
|
|
689
|
+
class ReliantRobinWithModule < Car
|
|
690
|
+
include Module.new
|
|
691
|
+
image_accessor :reliant_image
|
|
692
|
+
end
|
|
693
|
+
@subclass_with_module = ReliantRobinWithModule
|
|
694
|
+
@unrelated_class = Photo
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
it "should allow assigning base class accessors" do
|
|
698
|
+
@base_class.create! :image => 'blah'
|
|
699
|
+
end
|
|
700
|
+
it "should not allow assigning subclass accessors in the base class" do
|
|
701
|
+
@base_class.new.should_not respond_to(:reliant_image=)
|
|
702
|
+
end
|
|
703
|
+
it "should allow assigning base class accessors in the subclass" do
|
|
704
|
+
@subclass.create! :image => 'blah'
|
|
705
|
+
end
|
|
706
|
+
it "should allow assigning subclass accessors in the subclass" do
|
|
707
|
+
@subclass.create! :reliant_image => 'blah'
|
|
708
|
+
end
|
|
709
|
+
it "should allow assigning base class accessors in the subclass, even if it has mixins" do
|
|
710
|
+
@subclass_with_module.create! :image => 'blah'
|
|
711
|
+
end
|
|
712
|
+
it "should allow assigning subclass accessors in the subclass, even if it has mixins" do
|
|
713
|
+
@subclass_with_module.create! :reliant_image => 'blah'
|
|
714
|
+
end
|
|
715
|
+
it "return the correct apps for each accessors, even when names clash" do
|
|
716
|
+
@base_class.dragonfly_apps_for_attributes.should == {:image => @app}
|
|
717
|
+
@subclass.dragonfly_apps_for_attributes.should == {:image => @app, :reliant_image => @app}
|
|
718
|
+
@subclass_with_module.dragonfly_apps_for_attributes.should == {:image => @app, :reliant_image => @app}
|
|
719
|
+
@unrelated_class.dragonfly_apps_for_attributes.should == {:image => @app2}
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
end
|