Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
Added middleware_with_cache, so that we can more easily integrate int…
Browse files Browse the repository at this point in the history
…o rails (in two lines)
  • Loading branch information
Mark Evans committed Nov 14, 2009
1 parent 7168277 commit d33fa7e
Show file tree
Hide file tree
Showing 7 changed files with 97 additions and 60 deletions.
30 changes: 6 additions & 24 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ For the lazy rails user
In environment.rb:

config.gem 'dragonfly-rails', :lib => 'dragonfly/rails/images'
config.middleware.use 'Dragonfly::Middleware', :images

IMPORTANT: see 'Caching' below to add caching (recommended!)
config.middleware.use 'Dragonfly::MiddlewareWithCache', :images

Migration:

Expand All @@ -38,6 +36,8 @@ Model:
validates_mime_type_of :cover_image, :in => %w(image/jpeg image/png image/gif)
image_accessor :cover_image # This provides the reader/writer for cover_image
image_accessor :some_other_image # have as many as you like - each needs a xxxx_uid column as per migration above

end

Expand All @@ -53,30 +53,12 @@ View (for uploading via a file field):
View (to display):

<%= image_tag @album.cover_image.url('400x200') %>
<%= image_tag @album.cover_image.url('100x100!') %>
<%= image_tag @album.cover_image.url('100x100!', :png) %>
<%= image_tag @album.cover_image.url('100x100#') %>
<%= image_tag @album.cover_image.url('50x50+30+30sw') %>
<%= image_tag @album.cover_image.url('50x50+30+30sw', :tif) %>
<%= image_tag @album.cover_image.url(:rotate, 15) %>
...etc.


Caching
-------

All this processing and encoding on the fly is pretty expensive to perform on every page request.
Thankfully, HTTP caching comes to the rescue.
You could use any HTTP caching component such as Varnish, Squid, etc., but the quickest and easiest way is to use the excellent Rack::Cache, which should be adequate for most websites.

In that case, rather than the above, your `environment.rb` should contain something like this:

config.gem 'dragonfly-rails', :lib => 'dragonfly/rails/images'
config.gem 'rack-cache', :lib => 'rack/cache'
config.middleware.use 'Rack::Cache',
:verbose => true,
:metastore => 'file:/var/cache/rack/meta',
:entitystore => 'file:/var/cache/rack/body'
config.middleware.use 'Dragonfly::Middleware', :images


Using outside of rails, custom storage/processing/encoding/analysis, and more...
------------------------------------------------------------------------
Dragonfly is primarily a Rack app, the Rails part of it being nothing more than a separate layer on top of the main code, which means you can use it as a standalone app, or with Sinatra, Merb, etc.
Expand Down
1 change: 1 addition & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ begin
s.extra_rdoc_files = []
s.add_dependency('dragonfly')
s.add_dependency('rack')
s.add_dependency('rack-cache')
s.add_dependency('mime-types')
s.add_dependency('rmagick')
end
Expand Down
4 changes: 2 additions & 2 deletions lib/dragonfly/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def initialize(app, dragonfly_app_name)
end

def call(env)
response = dragonfly_app.call(env)
response = endpoint.call(env)
if response[0] == 404
@app.call(env)
else
Expand All @@ -18,7 +18,7 @@ def call(env)

private

def dragonfly_app
def endpoint
App[@dragonfly_app_name]
end

Expand Down
26 changes: 26 additions & 0 deletions lib/dragonfly/middleware_with_cache.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
require 'rack/cache'

module Dragonfly
class MiddlewareWithCache < Middleware

def initialize(app, dragonfly_app_name, rack_cache_opts={})
super(app, dragonfly_app_name)
@rack_cache_opts = {
:verbose => true,
:metastore => 'file:/var/cache/rack/meta',
:entitystore => 'file:/var/cache/rack/body'
}.merge(rack_cache_opts)
end

private

def endpoint
rack_cache_opts = @rack_cache_opts
@endpoint ||= Rack::Builder.new do
use Rack::Cache, rack_cache_opts
run super
end
end

end
end
38 changes: 4 additions & 34 deletions spec/dragonfly/middleware_spec.rb
Original file line number Diff line number Diff line change
@@ -1,44 +1,14 @@
require File.dirname(__FILE__) + '/../spec_helper'
require 'rack'
require File.dirname(__FILE__) + '/shared_middleware_spec'

describe Dragonfly::Middleware do

def make_request(app, url)
Rack::MockRequest.new(app).get(url)
end

before(:each) do
@stack = Rack::Builder.new do
use Dragonfly::Middleware, :images
run lambda{|env| [200, {"Content-Type" => "text/html"}, ["#{env['PATH_INFO']}, #{env['QUERY_STRING']}"]] }
run dummy_rack_app
end
end

it "should continue the calling chain if the app returns a 404 for that url" do
Dragonfly::App[:images].should_receive(:call).and_return(
[404, {"Content-Type" => 'text/plain'}, ['Not found']]
)
response = make_request(@stack, 'hello.png?howare=you')
response.status.should == 200
response.body.should == 'hello.png, howare=you'
end

it "should return as per the dragonfly app if the app returns a 200" do
Dragonfly::App[:images].should_receive(:call).and_return(
[200, {"Content-Type" => 'text/plain'}, ['ABCD']]
)
response = make_request(@stack, 'hello.png?howare=you')
response.status.should == 200
response.body.should == 'ABCD'
end

it "should return as per the dragonfly app if the app returns a 400" do
Dragonfly::App[:images].should_receive(:call).and_return(
[400, {"Content-Type" => 'text/plain'}, ['ABCD']]
)
response = make_request(@stack, 'hello.png?howare=you')
response.status.should == 400
response.body.should == 'ABCD'
end
it_should_behave_like 'dragonfly middleware'

end
end
14 changes: 14 additions & 0 deletions spec/dragonfly/middleware_with_cache_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
require File.dirname(__FILE__) + '/shared_middleware_spec'

describe Dragonfly::MiddlewareWithCache do

before(:each) do
@stack = Rack::Builder.new do
use Dragonfly::MiddlewareWithCache, :images
run dummy_rack_app
end
end

it_should_behave_like 'dragonfly middleware'

end
44 changes: 44 additions & 0 deletions spec/dragonfly/shared_middleware_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
require File.dirname(__FILE__) + '/../spec_helper'
require 'rack'

def dummy_rack_app
lambda{|env| [200, {"Content-Type" => "text/html"}, ["#{env['PATH_INFO']}, #{env['QUERY_STRING']}"]] }
end


describe "dragonfly middleware", :shared => true do

# REQUIRES THAT @stack and Dragonfly::App[:images] IS DEFINED

def make_request(app, url)
Rack::MockRequest.new(app).get(url)
end

it "should continue the calling chain if the app returns a 404 for that url" do
Dragonfly::App[:images].should_receive(:call).and_return(
[404, {"Content-Type" => 'text/plain'}, ['Not found']]
)
response = make_request(@stack, 'hello.png?howare=you')
response.status.should == 200
response.body.should == 'hello.png, howare=you'
end

it "should return as per the dragonfly app if the app returns a 200" do
Dragonfly::App[:images].should_receive(:call).and_return(
[200, {"Content-Type" => 'text/plain'}, ['ABCD']]
)
response = make_request(@stack, 'hello.png?howare=you')
response.status.should == 200
response.body.should == 'ABCD'
end

it "should return as per the dragonfly app if the app returns a 400" do
Dragonfly::App[:images].should_receive(:call).and_return(
[400, {"Content-Type" => 'text/plain'}, ['ABCD']]
)
response = make_request(@stack, 'hello.png?howare=you')
response.status.should == 400
response.body.should == 'ABCD'
end

end

0 comments on commit d33fa7e

Please sign in to comment.