oahu-dragonfly 0.8.2
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/.rspec +1 -0
- data/.yardopts +24 -0
- data/Gemfile +30 -0
- data/History.md +323 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/config.ru +14 -0
- data/docs.watchr +1 -0
- data/dragonfly.gemspec +297 -0
- data/extra_docs/Analysers.md +66 -0
- data/extra_docs/Caching.md +23 -0
- data/extra_docs/Configuration.md +124 -0
- data/extra_docs/Couch.md +49 -0
- data/extra_docs/DataStorage.md +153 -0
- data/extra_docs/Encoding.md +67 -0
- data/extra_docs/GeneralUsage.md +121 -0
- data/extra_docs/Generators.md +60 -0
- data/extra_docs/Heroku.md +50 -0
- data/extra_docs/ImageMagick.md +125 -0
- data/extra_docs/Index.md +33 -0
- data/extra_docs/MimeTypes.md +40 -0
- data/extra_docs/Models.md +272 -0
- data/extra_docs/Mongo.md +45 -0
- data/extra_docs/Processing.md +77 -0
- data/extra_docs/Rack.md +52 -0
- data/extra_docs/Rails2.md +57 -0
- data/extra_docs/Rails3.md +62 -0
- data/extra_docs/Sinatra.md +25 -0
- data/extra_docs/URLs.md +169 -0
- data/features/images.feature +47 -0
- data/features/no_processing.feature +14 -0
- data/features/rails_3.0.5.feature +8 -0
- data/features/steps/common_steps.rb +8 -0
- data/features/steps/dragonfly_steps.rb +66 -0
- data/features/steps/rails_steps.rb +28 -0
- data/features/support/env.rb +13 -0
- data/features/support/setup.rb +32 -0
- data/fixtures/rails_3.0.5/files/app/models/album.rb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/new.html.erb +7 -0
- data/fixtures/rails_3.0.5/files/app/views/albums/show.html.erb +6 -0
- data/fixtures/rails_3.0.5/files/config/initializers/dragonfly.rb +4 -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/rails_3.0.5/files/features/step_definitions/image_steps.rb +25 -0
- data/fixtures/rails_3.0.5/files/features/support/paths.rb +17 -0
- data/fixtures/rails_3.0.5/files/features/text_images.feature +7 -0
- data/fixtures/rails_3.0.5/template.rb +20 -0
- data/irbrc.rb +18 -0
- data/lib/dragonfly.rb +55 -0
- data/lib/dragonfly/active_model_extensions.rb +13 -0
- data/lib/dragonfly/active_model_extensions/attachment.rb +250 -0
- data/lib/dragonfly/active_model_extensions/attachment_class_methods.rb +148 -0
- data/lib/dragonfly/active_model_extensions/class_methods.rb +95 -0
- data/lib/dragonfly/active_model_extensions/instance_methods.rb +28 -0
- data/lib/dragonfly/active_model_extensions/validations.rb +41 -0
- data/lib/dragonfly/analyser.rb +58 -0
- data/lib/dragonfly/analysis/file_command_analyser.rb +32 -0
- data/lib/dragonfly/analysis/image_magick_analyser.rb +6 -0
- data/lib/dragonfly/app.rb +172 -0
- data/lib/dragonfly/config/heroku.rb +19 -0
- data/lib/dragonfly/config/image_magick.rb +6 -0
- data/lib/dragonfly/config/rails.rb +20 -0
- data/lib/dragonfly/configurable.rb +207 -0
- data/lib/dragonfly/core_ext/array.rb +7 -0
- data/lib/dragonfly/core_ext/hash.rb +7 -0
- data/lib/dragonfly/core_ext/object.rb +12 -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/couch_data_store.rb +64 -0
- data/lib/dragonfly/data_storage/file_data_store.rb +141 -0
- data/lib/dragonfly/data_storage/mongo_data_store.rb +86 -0
- data/lib/dragonfly/data_storage/s3data_store.rb +145 -0
- data/lib/dragonfly/encoder.rb +13 -0
- data/lib/dragonfly/encoding/image_magick_encoder.rb +6 -0
- data/lib/dragonfly/function_manager.rb +71 -0
- data/lib/dragonfly/generation/image_magick_generator.rb +6 -0
- data/lib/dragonfly/generator.rb +9 -0
- 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 +41 -0
- data/lib/dragonfly/image_magick/encoder.rb +57 -0
- data/lib/dragonfly/image_magick/generator.rb +145 -0
- data/lib/dragonfly/image_magick/processor.rb +99 -0
- data/lib/dragonfly/image_magick/utils.rb +72 -0
- data/lib/dragonfly/image_magick_utils.rb +4 -0
- data/lib/dragonfly/job.rb +451 -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 +20 -0
- data/lib/dragonfly/processing/image_magick_processor.rb +6 -0
- data/lib/dragonfly/processor.rb +9 -0
- data/lib/dragonfly/rails/images.rb +27 -0
- data/lib/dragonfly/response.rb +97 -0
- data/lib/dragonfly/routed_endpoint.rb +40 -0
- data/lib/dragonfly/serializer.rb +32 -0
- data/lib/dragonfly/server.rb +113 -0
- data/lib/dragonfly/simple_cache.rb +23 -0
- data/lib/dragonfly/temp_object.rb +175 -0
- data/lib/dragonfly/url_mapper.rb +78 -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/dragonfly/active_model_extensions/model_spec.rb +1426 -0
- data/spec/dragonfly/active_model_extensions/spec_helper.rb +91 -0
- data/spec/dragonfly/analyser_spec.rb +123 -0
- data/spec/dragonfly/analysis/file_command_analyser_spec.rb +48 -0
- data/spec/dragonfly/app_spec.rb +135 -0
- data/spec/dragonfly/configurable_spec.rb +461 -0
- data/spec/dragonfly/core_ext/array_spec.rb +19 -0
- data/spec/dragonfly/core_ext/hash_spec.rb +19 -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/couch_data_store_spec.rb +76 -0
- data/spec/dragonfly/data_storage/file_data_store_spec.rb +296 -0
- data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +57 -0
- data/spec/dragonfly/data_storage/s3_data_store_spec.rb +258 -0
- data/spec/dragonfly/data_storage/shared_data_store_examples.rb +77 -0
- data/spec/dragonfly/function_manager_spec.rb +154 -0
- data/spec/dragonfly/hash_with_css_style_keys_spec.rb +24 -0
- data/spec/dragonfly/image_magick/analyser_spec.rb +64 -0
- data/spec/dragonfly/image_magick/encoder_spec.rb +41 -0
- data/spec/dragonfly/image_magick/generator_spec.rb +172 -0
- data/spec/dragonfly/image_magick/processor_spec.rb +233 -0
- data/spec/dragonfly/image_magick/utils_spec.rb +18 -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 +173 -0
- data/spec/dragonfly/job_spec.rb +1046 -0
- data/spec/dragonfly/loggable_spec.rb +80 -0
- data/spec/dragonfly/middleware_spec.rb +47 -0
- data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
- data/spec/dragonfly/serializer_spec.rb +61 -0
- data/spec/dragonfly/server_spec.rb +278 -0
- data/spec/dragonfly/simple_cache_spec.rb +27 -0
- data/spec/dragonfly/temp_object_spec.rb +306 -0
- data/spec/dragonfly/url_mapper_spec.rb +126 -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 +51 -0
- data/spec/support/argument_matchers.rb +19 -0
- data/spec/support/image_matchers.rb +47 -0
- data/spec/support/simple_matchers.rb +53 -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 +89 -0
- data/yard/templates/default/module/html/configuration_summary.erb +31 -0
- data/yard/templates/default/module/setup.rb +17 -0
- metadata +544 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'active_model'
|
|
3
|
+
|
|
4
|
+
# --------------------------------------------------------------- #
|
|
5
|
+
# MODELS
|
|
6
|
+
# --------------------------------------------------------------- #
|
|
7
|
+
class MyModel
|
|
8
|
+
|
|
9
|
+
# Callbacks
|
|
10
|
+
extend ActiveModel::Callbacks
|
|
11
|
+
define_model_callbacks :save, :destroy
|
|
12
|
+
|
|
13
|
+
include ActiveModel::Validations
|
|
14
|
+
|
|
15
|
+
class << self
|
|
16
|
+
def create!(attrs={})
|
|
17
|
+
new(attrs).save!
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def find(id)
|
|
21
|
+
new(instances[id])
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def instances
|
|
25
|
+
@instances ||= {}
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def initialize(attrs={})
|
|
30
|
+
attrs.each do |key, value|
|
|
31
|
+
send("#{key}=", value)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
attr_accessor :id
|
|
36
|
+
|
|
37
|
+
def to_hash
|
|
38
|
+
self.class::ATTRIBUTES.inject({}) do |hash, attr|
|
|
39
|
+
hash[attr] = send(attr)
|
|
40
|
+
hash
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def save
|
|
45
|
+
_run_save_callbacks {
|
|
46
|
+
self.id ||= rand(1000)
|
|
47
|
+
self.class.instances[id] = self.to_hash
|
|
48
|
+
}
|
|
49
|
+
end
|
|
50
|
+
def save!
|
|
51
|
+
save
|
|
52
|
+
self
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def destroy
|
|
56
|
+
_run_destroy_callbacks {}
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class Item < MyModel
|
|
61
|
+
|
|
62
|
+
ATTRIBUTES = [
|
|
63
|
+
:title,
|
|
64
|
+
:preview_image_uid,
|
|
65
|
+
:preview_image_some_analyser_method,
|
|
66
|
+
:preview_image_size,
|
|
67
|
+
:preview_image_name,
|
|
68
|
+
:preview_image_blah_blah,
|
|
69
|
+
:other_image_uid,
|
|
70
|
+
:yet_another_image_uid,
|
|
71
|
+
:otra_imagen_uid,
|
|
72
|
+
:trailer_video_uid,
|
|
73
|
+
:created_at,
|
|
74
|
+
:updated_at
|
|
75
|
+
]
|
|
76
|
+
attr_accessor *ATTRIBUTES
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
class Car < MyModel
|
|
80
|
+
ATTRIBUTES = [
|
|
81
|
+
:image_uid,
|
|
82
|
+
:reliant_image_uid,
|
|
83
|
+
:type
|
|
84
|
+
]
|
|
85
|
+
attr_accessor *ATTRIBUTES
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
class Photo < MyModel
|
|
89
|
+
ATTRIBUTES = [:image_uid]
|
|
90
|
+
attr_accessor *ATTRIBUTES
|
|
91
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Dragonfly::Analyser do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@analyser = Dragonfly::Analyser.new
|
|
7
|
+
@analyser.log = Logger.new(LOG_FILE)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "analysis_methods module" do
|
|
11
|
+
|
|
12
|
+
before(:each) do
|
|
13
|
+
@analyser.add(:num_letters){|temp_object, letter| temp_object.data.count(letter) }
|
|
14
|
+
@obj = Object.new
|
|
15
|
+
@obj.extend @analyser.analysis_methods
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "should return a module" do
|
|
19
|
+
@analyser.analysis_methods.should be_a(Module)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should provide the object with the analyser method" do
|
|
23
|
+
@obj.analyser.should == @analyser
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should provide the object with the direct analysis method, provided that analyse method exists" do
|
|
27
|
+
def @obj.analyse(meth, *args)
|
|
28
|
+
analyser.analyse Dragonfly::TempObject.new('HELLO'), meth, *args
|
|
29
|
+
end
|
|
30
|
+
@obj.num_letters('L').should == 2
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
describe "analyse" do
|
|
36
|
+
it "should return nil if the function isn't defined" do
|
|
37
|
+
@analyser.analyse(Dragonfly::TempObject.new("Hello"), :width).should be_nil
|
|
38
|
+
end
|
|
39
|
+
it "should return nil if the function can't be handled" do
|
|
40
|
+
@analyser.add(:width){ throw :unable_to_handle }
|
|
41
|
+
@analyser.analyse(Dragonfly::TempObject.new("Hello"), :width).should be_nil
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "analysis_method_names" do
|
|
46
|
+
it "should return the analysis methods" do
|
|
47
|
+
@analyser.add(:width){}
|
|
48
|
+
@analyser.add(:height){}
|
|
49
|
+
@analyser.analysis_method_names.should == [:width, :height]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "cache" do
|
|
54
|
+
before(:each) do
|
|
55
|
+
@temp_object = Dragonfly::TempObject.new('HELLO')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def it_should_analyse_using(meth, temp_object, *args)
|
|
59
|
+
result = mock('result')
|
|
60
|
+
@analyser.should_receive(:call_last).with(meth, temp_object, *args).exactly(:once).and_return result
|
|
61
|
+
@analyser.analyse(temp_object, meth, *args).should == result
|
|
62
|
+
result
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should do the analysis the first time" do
|
|
66
|
+
it_should_analyse_using(:blah, @temp_object, :arg1)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "when already called" do
|
|
70
|
+
before(:each) do
|
|
71
|
+
@result = it_should_analyse_using(:blah, @temp_object, :arg1)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should not do it subsequent times but still return the result" do
|
|
75
|
+
@analyser.should_not_receive(:call_last)
|
|
76
|
+
@analyser.analyse(@temp_object, :blah, :arg1).should == @result
|
|
77
|
+
@analyser.analyse(@temp_object, :blah, :arg1).should == @result
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should not use the cache if the temp_object is different" do
|
|
81
|
+
temp_object = Dragonfly::TempObject.new('aaa')
|
|
82
|
+
it_should_analyse_using(:blah, temp_object, :arg1)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should not use the cache if the method name is different" do
|
|
86
|
+
it_should_analyse_using(:egghead, @temp_object, :arg1)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "should not use the cache if the args are different" do
|
|
90
|
+
it_should_analyse_using(:blah, @temp_object, :arg2)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should do it again if the cache has been cleared" do
|
|
94
|
+
@analyser.clear_cache!
|
|
95
|
+
it_should_analyse_using(:blah, @temp_object, :arg1)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should not use the cache if it has been turned off" do
|
|
99
|
+
@analyser.enable_cache = false
|
|
100
|
+
it_should_analyse_using(:blah, @temp_object, :arg1)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
describe "cache size" do
|
|
106
|
+
it "should not exceed the cache size" do
|
|
107
|
+
@analyser.cache_size = 2
|
|
108
|
+
|
|
109
|
+
res1 = it_should_analyse_using(:blah, @temp_object, :arg1)
|
|
110
|
+
res2 = it_should_analyse_using(:blah, @temp_object, :arg2)
|
|
111
|
+
res3 = it_should_analyse_using(:blah, @temp_object, :arg3) # Should kick out first one
|
|
112
|
+
|
|
113
|
+
it_should_analyse_using(:blah, @temp_object, :arg1)
|
|
114
|
+
|
|
115
|
+
# Third analysis should still be cached
|
|
116
|
+
@analyser.should_not_receive(:call_last)
|
|
117
|
+
@analyser.analyse(@temp_object, :blah, :arg3).should == res3
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
png_path = File.dirname(__FILE__) + '/../../../samples/egg.png'
|
|
4
|
+
|
|
5
|
+
describe Dragonfly::Analysis::FileCommandAnalyser do
|
|
6
|
+
|
|
7
|
+
before(:each) do
|
|
8
|
+
@analyser = Dragonfly::Analysis::FileCommandAnalyser.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "mime_type" do
|
|
12
|
+
|
|
13
|
+
describe "when using the filesystem" do
|
|
14
|
+
before(:each) do
|
|
15
|
+
@analyser.use_filesystem = true
|
|
16
|
+
@temp_object = Dragonfly::TempObject.new(File.new(png_path))
|
|
17
|
+
end
|
|
18
|
+
it "should give the mime-type" do
|
|
19
|
+
@analyser.mime_type(@temp_object).should == 'image/png'
|
|
20
|
+
end
|
|
21
|
+
it "should not have initialized the data string" do
|
|
22
|
+
@analyser.mime_type(@temp_object)
|
|
23
|
+
@temp_object.instance_eval{@data}.should be_nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "when not using the filesystem" do
|
|
28
|
+
before(:each) do
|
|
29
|
+
@analyser.use_filesystem = false
|
|
30
|
+
@temp_object = Dragonfly::TempObject.new(File.read(png_path))
|
|
31
|
+
end
|
|
32
|
+
it "should give the mime-type" do
|
|
33
|
+
@analyser.mime_type(@temp_object).should == 'image/png'
|
|
34
|
+
end
|
|
35
|
+
it "should not have initialized the file" do
|
|
36
|
+
@analyser.mime_type(@temp_object)
|
|
37
|
+
@temp_object.instance_eval{@tempfile}.should be_nil
|
|
38
|
+
end
|
|
39
|
+
it "should work properly (without a broken pipe error) for big files of format jpg" do
|
|
40
|
+
data = Dragonfly::ImageMagick::Generator.new.plasma(1000, 1000, :jpg).first
|
|
41
|
+
temp_object = Dragonfly::TempObject.new(data)
|
|
42
|
+
@analyser.mime_type(temp_object).should == "image/jpeg"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'rack/mock'
|
|
3
|
+
|
|
4
|
+
def request(app, path)
|
|
5
|
+
Rack::MockRequest.new(app).get(path)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe Dragonfly::App do
|
|
9
|
+
|
|
10
|
+
describe ".instance" do
|
|
11
|
+
|
|
12
|
+
it "should create a new instance if it didn't already exist" do
|
|
13
|
+
app = Dragonfly::App.instance(:images)
|
|
14
|
+
app.should be_a(Dragonfly::App)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should return an existing instance if called by name" do
|
|
18
|
+
app = Dragonfly::App.instance(:images)
|
|
19
|
+
Dragonfly::App.instance(:images).should == app
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should also work using square brackets" do
|
|
23
|
+
Dragonfly[:images].should == Dragonfly::App.instance(:images)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe ".new" do
|
|
29
|
+
it "should not be callable" do
|
|
30
|
+
lambda{
|
|
31
|
+
Dragonfly::App.new
|
|
32
|
+
}.should raise_error(NoMethodError)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "mime types" do
|
|
37
|
+
describe "#mime_type_for" do
|
|
38
|
+
before(:each) do
|
|
39
|
+
@app = test_app
|
|
40
|
+
end
|
|
41
|
+
it "should return the correct mime type for a symbol" do
|
|
42
|
+
@app.mime_type_for(:png).should == 'image/png'
|
|
43
|
+
end
|
|
44
|
+
it "should work for strings" do
|
|
45
|
+
@app.mime_type_for('png').should == 'image/png'
|
|
46
|
+
end
|
|
47
|
+
it "should work with uppercase strings" do
|
|
48
|
+
@app.mime_type_for('PNG').should == 'image/png'
|
|
49
|
+
end
|
|
50
|
+
it "should work with a dot" do
|
|
51
|
+
@app.mime_type_for('.png').should == 'image/png'
|
|
52
|
+
end
|
|
53
|
+
it "should return nil if not known" do
|
|
54
|
+
@app.mime_type_for(:mark).should be_nil
|
|
55
|
+
end
|
|
56
|
+
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'
|
|
59
|
+
end
|
|
60
|
+
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'
|
|
63
|
+
end
|
|
64
|
+
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'
|
|
69
|
+
other_app.mime_type_for(:mark).should == 'second/one'
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
describe "remote_url_for" do
|
|
75
|
+
before(:each) do
|
|
76
|
+
@app = test_app
|
|
77
|
+
@app.datastore = Object.new
|
|
78
|
+
end
|
|
79
|
+
it "should raise an error if the datastore doesn't provide it" do
|
|
80
|
+
lambda{
|
|
81
|
+
@app.remote_url_for('some_uid')
|
|
82
|
+
}.should raise_error(NotImplementedError)
|
|
83
|
+
end
|
|
84
|
+
it "should correctly call it if the datastore provides it" do
|
|
85
|
+
@app.datastore.should_receive(:url_for).with('some_uid', :some => :opts).and_return 'http://egg.head'
|
|
86
|
+
@app.remote_url_for('some_uid', :some => :opts).should == 'http://egg.head'
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe "#store" do
|
|
91
|
+
before(:each) do
|
|
92
|
+
@app = test_app
|
|
93
|
+
end
|
|
94
|
+
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(
|
|
105
|
+
a_temp_object_with_data("HELLO"), :meta => {:egg => :head}, :option => :blarney
|
|
106
|
+
)
|
|
107
|
+
@app.store("HELLO", :meta => {:egg => :head}, :option => :blarney)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
describe "url_for" do
|
|
112
|
+
before(:each) do
|
|
113
|
+
@app = test_app
|
|
114
|
+
@job = @app.fetch('eggs')
|
|
115
|
+
end
|
|
116
|
+
it "should give the server url by default" do
|
|
117
|
+
@app.url_for(@job).should =~ %r{^/\w+$}
|
|
118
|
+
end
|
|
119
|
+
it "should allow configuring" do
|
|
120
|
+
@app.configure do |c|
|
|
121
|
+
c.define_url do |app, job, opts|
|
|
122
|
+
"doogies"
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
@app.url_for(@job).should == 'doogies'
|
|
126
|
+
end
|
|
127
|
+
it "should yield the correct dooberries" do
|
|
128
|
+
@app.define_url do |app, job, opts|
|
|
129
|
+
[app, job, opts]
|
|
130
|
+
end
|
|
131
|
+
@app.url_for(@job, {'chuddies' => 'margate'}).should == [@app, @job, {'chuddies' => 'margate'}]
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
end
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Dragonfly::Configurable do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
class Car
|
|
7
|
+
include Dragonfly::Configurable
|
|
8
|
+
configurable_attr :colour
|
|
9
|
+
configurable_attr :top_speed, 216
|
|
10
|
+
def self.other_thing=(thing); end
|
|
11
|
+
end
|
|
12
|
+
@car = Car.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "setup" do
|
|
16
|
+
it "should provide attr_readers for configurable attributes" do
|
|
17
|
+
@car.should respond_to(:colour)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should provide attr_writers for configurable attributes" do
|
|
21
|
+
@car.colour = 'verde'
|
|
22
|
+
@car.colour.should == 'verde'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should set default values for configurable attributes" do
|
|
26
|
+
@car.top_speed.should == 216
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should set the default as nil if not specified" do
|
|
30
|
+
@car.colour.should be_nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should allow 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'
|
|
42
|
+
end
|
|
43
|
+
Bike.new.colour.should == 'rude'
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
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 "using in the singleton class" do
|
|
123
|
+
it "should work" do
|
|
124
|
+
class OneOff
|
|
125
|
+
class << self
|
|
126
|
+
include Dragonfly::Configurable
|
|
127
|
+
configurable_attr :food, 'bread'
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
OneOff.food.should == 'bread'
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
describe "configuration method" do
|
|
135
|
+
|
|
136
|
+
before(:each) do
|
|
137
|
+
class ClassWithMethod
|
|
138
|
+
include Dragonfly::Configurable
|
|
139
|
+
def add_thing(thing)
|
|
140
|
+
'poo'
|
|
141
|
+
end
|
|
142
|
+
def remove_thing(thing)
|
|
143
|
+
'bum'
|
|
144
|
+
end
|
|
145
|
+
configuration_method :add_thing, :remove_thing
|
|
146
|
+
end
|
|
147
|
+
@thing = ClassWithMethod.new
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should allow calling the method through 'configure'" do
|
|
151
|
+
@thing.configure do |c|
|
|
152
|
+
c.add_thing('duck')
|
|
153
|
+
c.remove_thing('dog')
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe "nested configurable objects" do
|
|
160
|
+
|
|
161
|
+
before(:each) do
|
|
162
|
+
class NestedThing
|
|
163
|
+
include Dragonfly::Configurable
|
|
164
|
+
configurable_attr :age, 29
|
|
165
|
+
def some_method(val)
|
|
166
|
+
@some_thing = val
|
|
167
|
+
end
|
|
168
|
+
configuration_method :some_method
|
|
169
|
+
attr_reader :some_thing
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
class Car
|
|
173
|
+
def nested_thing
|
|
174
|
+
@nested_thing ||= NestedThing.new
|
|
175
|
+
end
|
|
176
|
+
nested_configurable :nested_thing
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
@car.configure do |c|
|
|
180
|
+
c.nested_thing.configure do |nt|
|
|
181
|
+
nt.age = 50
|
|
182
|
+
nt.some_method('yo')
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it "should allow configuring nested configurable accessors" do
|
|
188
|
+
@car.nested_thing.age.should == 50
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "should allow configuring nested configurable normal methods" do
|
|
192
|
+
@car.nested_thing.some_thing.should == 'yo'
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it "should not allow configuring directly on the config object" do
|
|
196
|
+
expect{
|
|
197
|
+
@car.configure do |c|
|
|
198
|
+
c.some_method('other')
|
|
199
|
+
end
|
|
200
|
+
}.to raise_error(Dragonfly::Configurable::BadConfigAttribute)
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
describe "configuring with a saved config" do
|
|
205
|
+
before(:each) do
|
|
206
|
+
@cool_configuration = Object.new
|
|
207
|
+
def @cool_configuration.apply_configuration(car, colour=nil)
|
|
208
|
+
car.configure do |c|
|
|
209
|
+
c.colour = (colour || 'vermelho')
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "should allow configuration by a saved config" do
|
|
215
|
+
@car.configure_with(@cool_configuration)
|
|
216
|
+
@car.colour.should == 'vermelho'
|
|
217
|
+
@car.top_speed.should == 216
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "should pass any args through to the saved config" do
|
|
221
|
+
@car.configure_with(@cool_configuration, 'preto')
|
|
222
|
+
@car.colour.should == 'preto'
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it "should yield a block for any extra configuration" do
|
|
226
|
+
@car.configure_with(@cool_configuration) do |c|
|
|
227
|
+
c.colour = 'branco'
|
|
228
|
+
end
|
|
229
|
+
@car.colour.should == 'branco'
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "should return itself" do
|
|
233
|
+
@car.configure_with(@cool_configuration).should == @car
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
describe "using a symbol to specify the config" do
|
|
237
|
+
|
|
238
|
+
before(:all) do
|
|
239
|
+
@rally_config = Object.new
|
|
240
|
+
Car.register_configuration(:rally, @rally_config)
|
|
241
|
+
@long_journey_config = Object.new
|
|
242
|
+
Car.register_configuration(:long_journey){ @long_journey_config }
|
|
243
|
+
Car.register_configuration(:some_library){ SomeLibrary }
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should map the symbol to the correct configuration" do
|
|
247
|
+
@rally_config.should_receive(:apply_configuration).with(@car)
|
|
248
|
+
@car.configure_with(:rally)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it "should map the symbol to the correct configuration lazily" do
|
|
252
|
+
@long_journey_config.should_receive(:apply_configuration).with(@car)
|
|
253
|
+
@car.configure_with(:long_journey)
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
it "should throw an error if an unknown symbol is passed in" do
|
|
257
|
+
lambda {
|
|
258
|
+
@car.configure_with(:eggs)
|
|
259
|
+
}.should raise_error(ArgumentError)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it "should only try to load the library when asked to" do
|
|
263
|
+
lambda{
|
|
264
|
+
@car.configure_with(:some_library)
|
|
265
|
+
}.should raise_error(NameError, /uninitialized constant.*SomeLibrary/)
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
describe "falling back to another config" do
|
|
272
|
+
before(:each) do
|
|
273
|
+
@garage = Object.new
|
|
274
|
+
class << @garage
|
|
275
|
+
include Dragonfly::Configurable
|
|
276
|
+
configurable_attr :top_speed, 100
|
|
277
|
+
end
|
|
278
|
+
@car.use_as_fallback_config(@garage)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
describe "when nothing set" do
|
|
282
|
+
it "should use its default" do
|
|
283
|
+
@car.top_speed.should == 216
|
|
284
|
+
end
|
|
285
|
+
it "shouldn't affect the fallback config object" do
|
|
286
|
+
@garage.top_speed.should == 100
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
describe "if set" do
|
|
291
|
+
before(:each) do
|
|
292
|
+
@car.top_speed = 444
|
|
293
|
+
end
|
|
294
|
+
it "should work normally" do
|
|
295
|
+
@car.top_speed.should == 444
|
|
296
|
+
end
|
|
297
|
+
it "shouldn't affect the fallback config object" do
|
|
298
|
+
@garage.top_speed.should == 100
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
describe "both set" do
|
|
303
|
+
before(:each) do
|
|
304
|
+
@car.top_speed = 444
|
|
305
|
+
@garage.top_speed = 3000
|
|
306
|
+
end
|
|
307
|
+
it "should prefer its own setting" do
|
|
308
|
+
@car.top_speed.should == 444
|
|
309
|
+
end
|
|
310
|
+
it "shouldn't affect the fallback config object" do
|
|
311
|
+
@garage.top_speed.should == 3000
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
describe "the fallback config is set" do
|
|
316
|
+
before(:each) do
|
|
317
|
+
@garage.top_speed = 3000
|
|
318
|
+
end
|
|
319
|
+
it "should use the fallback config" do
|
|
320
|
+
@car.top_speed.should == 3000
|
|
321
|
+
end
|
|
322
|
+
it "shouldn't affect the fallback config object" do
|
|
323
|
+
@garage.top_speed.should == 3000
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
describe "falling back multiple levels" do
|
|
328
|
+
before(:each) do
|
|
329
|
+
@klass = Class.new
|
|
330
|
+
@klass.class_eval do
|
|
331
|
+
include Dragonfly::Configurable
|
|
332
|
+
configurable_attr :veg, 'carrot'
|
|
333
|
+
end
|
|
334
|
+
@a = @klass.new
|
|
335
|
+
@b = @klass.new
|
|
336
|
+
@b.use_as_fallback_config(@a)
|
|
337
|
+
@c = @klass.new
|
|
338
|
+
@c.use_as_fallback_config(@b)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
it "should be the default if nothing set" do
|
|
342
|
+
@c.veg.should == 'carrot'
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "should fall all the way back to the top one if necessary" do
|
|
346
|
+
@a.veg = 'turnip'
|
|
347
|
+
@c.veg.should == 'turnip'
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
it "should prefer the closer one over the further away one" do
|
|
351
|
+
@b.veg = 'tatty'
|
|
352
|
+
@a.veg = 'turnip'
|
|
353
|
+
@c.veg.should == 'tatty'
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
it "should work properly with nils" do
|
|
357
|
+
@a.veg = nil
|
|
358
|
+
@c.veg = 'broc'
|
|
359
|
+
@a.veg.should be_nil
|
|
360
|
+
@b.veg.should be_nil
|
|
361
|
+
@c.veg.should == 'broc'
|
|
362
|
+
end
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
describe "objects with different methods" do
|
|
366
|
+
before(:each) do
|
|
367
|
+
@dad = Object.new
|
|
368
|
+
class << @dad
|
|
369
|
+
include Dragonfly::Configurable
|
|
370
|
+
end
|
|
371
|
+
@kid = Object.new
|
|
372
|
+
class << @kid
|
|
373
|
+
include Dragonfly::Configurable
|
|
374
|
+
configurable_attr :lug, 'default-lug'
|
|
375
|
+
end
|
|
376
|
+
@kid.use_as_fallback_config(@dad)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it "should not allow setting on the fallback obj directly" do
|
|
380
|
+
lambda{
|
|
381
|
+
@dad.lug = 'leg'
|
|
382
|
+
}.should raise_error(NoMethodError)
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it "should not have the fallback obj respond to the method" do
|
|
386
|
+
@dad.should_not respond_to(:lug=)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
it "should allow configuring through the fallback object even if it doesn't have that method" do
|
|
390
|
+
@dad.configure do |c|
|
|
391
|
+
c.lug = 'leg'
|
|
392
|
+
end
|
|
393
|
+
@kid.lug.should == 'leg'
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
it "should work when a grandchild config is added later" do
|
|
397
|
+
grandkid = Object.new
|
|
398
|
+
class << grandkid
|
|
399
|
+
include Dragonfly::Configurable
|
|
400
|
+
configurable_attr :oogie, 'boogie'
|
|
401
|
+
end
|
|
402
|
+
grandkid.use_as_fallback_config(@kid)
|
|
403
|
+
@dad.configure{|c| c.oogie = 'duggen' }
|
|
404
|
+
grandkid.oogie.should == 'duggen'
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it "should allow configuring twice through the fallback object" do
|
|
408
|
+
@dad.configure{|c| c.lug = 'leg' }
|
|
409
|
+
@dad.configure{|c| c.lug = 'blug' }
|
|
410
|
+
@kid.lug.should == 'blug'
|
|
411
|
+
end
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
describe "clashing with configurable modules" do
|
|
415
|
+
before(:each) do
|
|
416
|
+
@mod = mod = Module.new
|
|
417
|
+
@mod.module_eval do
|
|
418
|
+
include Dragonfly::Configurable
|
|
419
|
+
configurable_attr :team, 'spurs'
|
|
420
|
+
end
|
|
421
|
+
@class = Class.new
|
|
422
|
+
@class.class_eval do
|
|
423
|
+
include mod
|
|
424
|
+
include Dragonfly::Configurable
|
|
425
|
+
configurable_attr :tree, 'elm'
|
|
426
|
+
end
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
it "should not override the defaults from the module" do
|
|
430
|
+
obj = @class.new
|
|
431
|
+
obj.team.should == 'spurs'
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
it "should still use its own defaults" do
|
|
435
|
+
obj = @class.new
|
|
436
|
+
obj.tree.should == 'elm'
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
describe "when the configurable_attr is specified in a subclass that doesn't include Configurable" do
|
|
440
|
+
before(:each) do
|
|
441
|
+
@subclass = Class.new(@class)
|
|
442
|
+
@subclass.class_eval do
|
|
443
|
+
configurable_attr :car, 'mazda'
|
|
444
|
+
configurable_attr :tree, 'oak'
|
|
445
|
+
end
|
|
446
|
+
@obj = @subclass.new
|
|
447
|
+
end
|
|
448
|
+
|
|
449
|
+
it "should still work with default values" do
|
|
450
|
+
@obj.car.should == 'mazda'
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
it "should override the default from the parent" do
|
|
454
|
+
@obj.tree.should == 'oak'
|
|
455
|
+
end
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
end
|
|
461
|
+
end
|