oahu-dragonfly 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- 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,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'deprecations' do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@app = test_app
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "url_suffix" do
|
10
|
+
it "should give an appropriate error" do
|
11
|
+
@app.configure do |c|
|
12
|
+
expect{
|
13
|
+
c.url_suffix = 'darble'
|
14
|
+
}.to raise_error(NoMethodError, /deprecated.*please use url_format/)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "url_path_prefix" do
|
20
|
+
it "should give an appropriate error" do
|
21
|
+
@app.configure do |c|
|
22
|
+
expect{
|
23
|
+
c.url_path_prefix = '/darble'
|
24
|
+
}.to raise_error(NoMethodError, /deprecated.*please use url_format/)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "middleware" do
|
30
|
+
it "should give an appropriate error" do
|
31
|
+
app = Rack::Builder.new do
|
32
|
+
use Dragonfly::Middleware, :images, '/media'
|
33
|
+
run proc{[200, {}, []]}
|
34
|
+
end
|
35
|
+
expect{
|
36
|
+
app.call({})
|
37
|
+
}.to raise_error(ArgumentError, /deprecated/)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "infer_mime_type_from_file_ext" do
|
42
|
+
it "should give an appropriate error" do
|
43
|
+
@app.configure do |c|
|
44
|
+
expect{
|
45
|
+
c.infer_mime_type_from_file_ext = false
|
46
|
+
}.to raise_error(NoMethodError, /deprecated.*please use trust_file_extensions = false/)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "a configured imagemagick app" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@app = Dragonfly[:images].configure_with(:imagemagick)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "convert command path" do
|
10
|
+
before(:each) do
|
11
|
+
@processor = @app.processor.get_registered(Dragonfly::ImageMagick::Processor)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should default to 'convert'" do
|
15
|
+
@processor.convert_command.should == 'convert'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should change when configured through the app" do
|
19
|
+
@app.configure do |c|
|
20
|
+
c.convert_command = '/usr/eggs'
|
21
|
+
end
|
22
|
+
@processor.convert_command.should == '/usr/eggs'
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'dragonfly/active_model_extensions/spec_helper'
|
2
|
+
require 'tempfile'
|
3
|
+
|
4
|
+
describe "model urls" do
|
5
|
+
|
6
|
+
def new_tempfile(data='HELLO', filename='hello.txt')
|
7
|
+
tempfile = Tempfile.new('test')
|
8
|
+
tempfile.write(data)
|
9
|
+
tempfile.rewind
|
10
|
+
tempfile.stub!(:original_filename).and_return(filename)
|
11
|
+
tempfile
|
12
|
+
end
|
13
|
+
|
14
|
+
before(:each) do
|
15
|
+
@app = test_app.configure do |c|
|
16
|
+
c.url_format = '/media/:job/:basename.:format'
|
17
|
+
end
|
18
|
+
@app.define_macro(MyModel, :image_accessor)
|
19
|
+
Item.class_eval do
|
20
|
+
image_accessor :preview_image # has name etc.
|
21
|
+
image_accessor :other_image # doesn't have magic stuff
|
22
|
+
end
|
23
|
+
@item = Item.new
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should include the name in the url if it has the magic attribute" do
|
27
|
+
@item.preview_image = new_tempfile
|
28
|
+
@item.save!
|
29
|
+
item = Item.find(@item.id)
|
30
|
+
item.preview_image.url.should =~ %r{^/media/\w+/hello\.txt$}
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should work without the name if the name magic attr doesn't exist" do
|
34
|
+
@item.other_image = new_tempfile
|
35
|
+
@item.save!
|
36
|
+
item = Item.find(@item.id)
|
37
|
+
item.other_image.url.should =~ %r{^/media/\w+$}
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should include the name in the url even if it has no ext" do
|
41
|
+
@item.preview_image = new_tempfile("hello", 'hello')
|
42
|
+
@item.save!
|
43
|
+
item = Item.find(@item.id)
|
44
|
+
item.preview_image.url.should =~ %r{^/media/\w+/hello$}
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should change the ext when there's an encoding step" do
|
48
|
+
@item.preview_image = new_tempfile
|
49
|
+
@item.save!
|
50
|
+
item = Item.find(@item.id)
|
51
|
+
item.preview_image.encode(:bum).url.should =~ %r{^/media/\w+/hello\.bum$}
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should not include the name if it has none" do
|
55
|
+
@item.preview_image = "HELLO"
|
56
|
+
@item.save!
|
57
|
+
item = Item.find(@item.id)
|
58
|
+
item.preview_image.url.should =~ %r{^/media/\w+$}
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should have an ext when there's an encoding step but no name" do
|
62
|
+
@item.preview_image = "HELLO"
|
63
|
+
@item.save!
|
64
|
+
item = Item.find(@item.id)
|
65
|
+
item.preview_image.encode(:bum).url.should =~ %r{^/media/\w+\.bum$}
|
66
|
+
end
|
67
|
+
|
68
|
+
it "should work as normal with dos protection" do
|
69
|
+
@app.server.protect_from_dos_attacks = true
|
70
|
+
@item.preview_image = new_tempfile
|
71
|
+
@item.save!
|
72
|
+
item = Item.find(@item.id)
|
73
|
+
item.preview_image.url.should =~ %r{^/media/\w+/hello\.txt\?sha=\w+$}
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should allow configuring the url" do
|
77
|
+
@app.configure do |c|
|
78
|
+
c.url_format = '/img/:job'
|
79
|
+
end
|
80
|
+
@item.preview_image = new_tempfile
|
81
|
+
@item.save!
|
82
|
+
item = Item.find(@item.id)
|
83
|
+
item.preview_image.url.should =~ %r{^/img/\w+$}
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "remote on-the-fly urls" do
|
4
|
+
|
5
|
+
THUMBS = {}
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
@app = test_app.configure do |c|
|
9
|
+
c.generator.add :test do
|
10
|
+
"TEST"
|
11
|
+
end
|
12
|
+
c.server.before_serve do |job, env|
|
13
|
+
uid = job.store(:path => 'yay.txt')
|
14
|
+
THUMBS[job.serialize] = uid
|
15
|
+
end
|
16
|
+
c.define_url do |app, job, opts|
|
17
|
+
uid = THUMBS[job.serialize]
|
18
|
+
if uid
|
19
|
+
app.datastore.url_for(uid)
|
20
|
+
else
|
21
|
+
app.server.url_for(job)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
c.datastore = Dragonfly::DataStorage::FileDataStore.new
|
25
|
+
c.datastore.root_path = '/var/tmp/dragonfly'
|
26
|
+
c.datastore.server_root = '/var/tmp'
|
27
|
+
end
|
28
|
+
@job = @app.generate(:test)
|
29
|
+
end
|
30
|
+
|
31
|
+
after(:each) do
|
32
|
+
THUMBS.delete_if{true}
|
33
|
+
FileUtils.rm_f('/var/tmp/dragonfly/yay.txt')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should give the url for the server" do
|
37
|
+
@job.url.should == "/#{@job.serialize}"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should store the content when first called" do
|
41
|
+
File.exist?('/var/tmp/dragonfly/yay.txt').should be_false
|
42
|
+
@app.server.call('PATH_INFO' => @job.url, 'REQUEST_METHOD' => 'GET')
|
43
|
+
File.read('/var/tmp/dragonfly/yay.txt').should == 'TEST'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should point to the external url the second time" do
|
47
|
+
@app.server.call('PATH_INFO' => @job.url, 'REQUEST_METHOD' => 'GET')
|
48
|
+
@job.url.should == '/dragonfly/yay.txt'
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "getting rack response directly" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@app = Dragonfly[:to_response].configure do |c|
|
7
|
+
c.generator.add :test do
|
8
|
+
"bunheads"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should give a rack response" do
|
14
|
+
response = @app.generate(:test, 1, 1).to_response
|
15
|
+
response.should be_a(Array)
|
16
|
+
response.length.should == 3
|
17
|
+
response[0].should == 200
|
18
|
+
response[1]['Content-Type'].should == 'application/octet-stream'
|
19
|
+
response[2].data.should == 'bunheads'
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should allow passing in the env" do
|
23
|
+
response = @app.generate(:test, 1, 1).to_response('REQUEST_METHOD' => 'POST')
|
24
|
+
response.should be_a(Array)
|
25
|
+
response.length.should == 3
|
26
|
+
response[0].should == 405
|
27
|
+
response[1]['Content-Type'].should == 'text/plain'
|
28
|
+
response[2].should == ["POST method not allowed"]
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
Bundler.setup(:default, :test)
|
4
|
+
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
7
|
+
require 'rspec'
|
8
|
+
require 'dragonfly'
|
9
|
+
require 'fileutils'
|
10
|
+
|
11
|
+
require 'webmock/rspec'
|
12
|
+
|
13
|
+
# Requires supporting files with custom matchers and macros, etc,
|
14
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
15
|
+
|
16
|
+
SAMPLES_DIR = File.expand_path(File.dirname(__FILE__) + '/../samples') unless defined?(SAMPLES_DIR)
|
17
|
+
|
18
|
+
def todo
|
19
|
+
raise "TODO"
|
20
|
+
end
|
21
|
+
|
22
|
+
require 'logger'
|
23
|
+
LOG_FILE = File.dirname(__FILE__) + '/spec.log' unless defined?(LOG_FILE)
|
24
|
+
FileUtils.rm_rf(LOG_FILE)
|
25
|
+
def mock_app(extra_stubs={})
|
26
|
+
mock('app', {
|
27
|
+
:datastore => mock('datastore', :store => 'some_uid', :retrieve => ["SOME_DATA", {}], :destroy => nil),
|
28
|
+
:processor => mock('processor', :process => "SOME_PROCESSED_DATA"),
|
29
|
+
:encoder => mock('encoder', :encode => "SOME_ENCODED_DATA"),
|
30
|
+
:analyser => mock('analyser', :analyse => "some_result", :analysis_methods => Module.new),
|
31
|
+
:generator => mock('generator', :generate => "SOME_GENERATED_DATA"),
|
32
|
+
:log => Logger.new(LOG_FILE),
|
33
|
+
:cache_duration => 10000,
|
34
|
+
:job_definitions => Module.new
|
35
|
+
}.merge(extra_stubs)
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_app
|
40
|
+
Dragonfly::App.send(:new)
|
41
|
+
end
|
42
|
+
|
43
|
+
def suppressing_stderr
|
44
|
+
original_stderr = $stderr.dup
|
45
|
+
tempfile = Tempfile.new('stderr')
|
46
|
+
$stderr.reopen(tempfile)
|
47
|
+
yield
|
48
|
+
ensure
|
49
|
+
tempfile.close!
|
50
|
+
$stderr.reopen(original_stderr)
|
51
|
+
end
|
@@ -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,47 @@
|
|
1
|
+
def image_properties(image)
|
2
|
+
if image.is_a?(Tempfile)
|
3
|
+
tempfile = image
|
4
|
+
else
|
5
|
+
tempfile = Tempfile.new('image')
|
6
|
+
tempfile.write(image.is_a?(Dragonfly::TempObject) ? image.data : image)
|
7
|
+
tempfile.close
|
8
|
+
end
|
9
|
+
details = `identify #{tempfile.path}`
|
10
|
+
# example of details string:
|
11
|
+
# myimage.png PNG 200x100 200x100+0+0 8-bit DirectClass 31.2kb
|
12
|
+
filename, format, geometry, geometry_2, depth, image_class, size = details.split(' ')
|
13
|
+
width, height = geometry.split('x')
|
14
|
+
{
|
15
|
+
:filename => filename,
|
16
|
+
:format => format.downcase,
|
17
|
+
:width => width,
|
18
|
+
:height => height,
|
19
|
+
:depth => depth,
|
20
|
+
:image_class => image_class,
|
21
|
+
:size => size
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
RSpec::Matchers.define :have_width do |width|
|
26
|
+
match do |given|
|
27
|
+
width.should === image_properties(given)[:width].to_i
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
RSpec::Matchers.define :have_height do |height|
|
32
|
+
match do |given|
|
33
|
+
height.should === image_properties(given)[:height].to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
RSpec::Matchers.define :have_format do |format|
|
38
|
+
match do |given|
|
39
|
+
image_properties(given)[:format].should == format
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
RSpec::Matchers.define :have_size do |size|
|
44
|
+
match do |given|
|
45
|
+
image_properties(given)[:size].should == size
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
RSpec::Matchers.define :match_url do |url|
|
2
|
+
match do |given|
|
3
|
+
given_path, given_query_string = given.split('?')
|
4
|
+
path, query_string = url.split('?')
|
5
|
+
|
6
|
+
path == given_path && given_query_string.split('&').sort == query_string.split('&').sort
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec::Matchers.define :be_an_empty_directory do
|
11
|
+
match do |given|
|
12
|
+
Dir.entries(given) == ['.','..']
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec::Matchers.define :include_hash do |hash|
|
17
|
+
match do |given|
|
18
|
+
given.merge(hash) == given
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def memory_usage
|
23
|
+
GC.start # Garbage collect
|
24
|
+
`ps -o rss= -p #{$$}`.strip.to_i
|
25
|
+
end
|
26
|
+
|
27
|
+
RSpec::Matchers.define :leak_memory do
|
28
|
+
match do |given|
|
29
|
+
memory_before = memory_usage
|
30
|
+
given.call
|
31
|
+
memory_after = memory_usage
|
32
|
+
result = memory_after > memory_before
|
33
|
+
puts "#{memory_after} > #{memory_before}" if result
|
34
|
+
result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
RSpec::Matchers.define :match_attachment_classes do |classes|
|
39
|
+
match do |given_classes|
|
40
|
+
given_classes.length == classes.length &&
|
41
|
+
classes.zip(given_classes).all? do |(klass, given)|
|
42
|
+
given.model_class == klass[0] && given.attribute == klass[1] && given.app == klass[2]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
RSpec::Matchers.define :be_a_text_response do
|
48
|
+
match do |given_response|
|
49
|
+
given_response.status.should == 200
|
50
|
+
given_response.body.length.should > 0
|
51
|
+
given_response.content_type.should == 'text/plain'
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class ConfigurableAttrHandler < YARD::Handlers::Ruby::Legacy::Base
|
2
|
+
handles(/^\s*configurable_attr/)
|
3
|
+
|
4
|
+
def process
|
5
|
+
namespace[:configurable_attributes] ||= []
|
6
|
+
|
7
|
+
attribute = token_to_object(statement.tokens[2])
|
8
|
+
comments = statement.comments.join(' ') if statement.comments
|
9
|
+
|
10
|
+
if statement.block
|
11
|
+
# e.g. configurable_attr :datastore do FileDataStore.new end
|
12
|
+
lazy_default_value = statement.block.to_s
|
13
|
+
else
|
14
|
+
# e.g. configurable_attr :fallback_mime_type, 'application/octet-stream'
|
15
|
+
default_value = token_to_object(statement.tokens[5..-1])
|
16
|
+
end
|
17
|
+
namespace[:configurable_attributes] << {
|
18
|
+
:attribute => attribute,
|
19
|
+
:default_value => default_value,
|
20
|
+
:lazy_default_value => lazy_default_value,
|
21
|
+
:comments => comments
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def token_to_object(token)
|
28
|
+
if token
|
29
|
+
if token.is_a?(YARD::Parser::Ruby::Legacy::TokenList)
|
30
|
+
eval(token.to_s)
|
31
|
+
else # is a single token
|
32
|
+
eval(token.text)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|