Permalink
Browse files

Middleware to fetch static pages

  • Loading branch information...
1 parent 595f002 commit dc9a2d7c1e8016815d352ddb5f390dfc17fc14a6 Joe Ferris and Mike Burns committed with jferris Aug 3, 2012
View
@@ -2,3 +2,5 @@
require 'turning/callbacks'
require 'turning/controller'
require 'turning/renderer'
+require 'turning/static_cascade'
+require 'turning/railtie'
@@ -0,0 +1,32 @@
+module Turning
+ class FileStorage
+ def initialize(root_path)
+ @root_path = root_path
+ end
+
+ def put(file_path, contents)
+ FileUtils.mkdir_p(parent_directory(file_path))
+ File.open(resolve(file_path), 'w') do |file|
+ file.write(contents)
+ end
+ end
+
+ def get(file_path)
+ begin
+ IO.read(resolve(file_path))
+ rescue Errno::ENOENT
+ nil
+ end
+ end
+
+ private
+
+ def resolve(file_path)
+ File.join(@root_path, file_path)
+ end
+
+ def parent_directory(file_path)
+ File.dirname(resolve(file_path))
+ end
+ end
+end
@@ -0,0 +1,12 @@
+require 'rails/railtie'
+require 'turning/static_cascade'
+require 'turning/file_storage'
+
+module Turning
+ class Railtie < ::Rails::Railtie
+ initializer('turning.middleware') do
+ config.app_middleware.use StaticCascade,
+ FileStorage.new(Rails.root.join('public', 'static'))
+ end
+ end
+end
@@ -54,7 +54,7 @@ def render_to_file(template_name, assigns)
private
def target_path
- Rails.root.join('public', 'cached', @controller_path)
+ Rails.root.join('public', 'static', @controller_path)
end
end
end
@@ -0,0 +1,18 @@
+module Turning
+ class StaticCascade
+ def initialize(app, storage)
+ @app = app
+ @storage = storage
+ end
+
+ def call(env)
+ if body = @storage.get(env['PATH_INFO'])
+ content_length = body.size
+ headers = { 'Content-Type' => 'text/html', 'Content-Length' => content_length.to_s }
+ [200, headers, [body]]
+ else
+ @app.call(env)
+ end
+ end
+ end
+end
View
@@ -1,6 +1,7 @@
require 'rspec'
require 'turning'
require 'bourne'
+require 'rack/test'
require './spec/testapp/config/application'
Dir["spec/support/**/*.rb"].each { |f| require File.expand_path(f) }
@@ -7,16 +7,16 @@ def create_view(path, contents)
@view_files << full_path
end
- def read_cached_view(path)
- IO.read(Rails.root.join('public', 'cached', path))
+ def read_static_view(path)
+ IO.read(Rails.root.join('public', 'static', path))
end
def cleanup_views
(@view_files || []).each do |view_file|
FileUtils.rm_rf(view_file)
end
- FileUtils.rm_rf(Rails.root.join('public', 'cached'))
+ FileUtils.rm_rf(Rails.root.join('public', 'static'))
end
end
@@ -82,3 +82,53 @@
Rendered examples/greet_hello.html.erb (0.2ms)
Rendered examples/form.html.erb (0.5ms)
Rendered examples/simple.html.erb within layouts/static (0.2ms)
+ Rendered examples/index.html.erb (1.1ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 11:51:44 -0400
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 12:08:42 -0400
+ Rendered examples/index.html.erb (1.1ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 12:10:16 -0400
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 12:21:18 -0400
+ Rendered examples/say_hello.html.erb (0.3ms)
+ Rendered examples/go_home.html.erb (13.0ms)
+ Rendered examples/greet_hello.html.erb (0.2ms)
+ Rendered examples/form.html.erb (0.5ms)
+ Rendered examples/simple.html.erb within layouts/static (0.2ms)
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 12:56:47 -0400
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 12:59:04 -0400
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 12:59:43 -0400
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/" for 127.0.0.1 at 2012-08-03 13:00:24 -0400
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/examples/index.html" for 127.0.0.1 at 2012-08-03 13:03:18 -0400
+ Rendered examples/index.html.erb (1.0ms)
+
+
+Started GET "/examples/index.html" for 127.0.0.1 at 2012-08-03 13:03:22 -0400
+ Rendered examples/say_hello.html.erb (0.2ms)
+ Rendered examples/go_home.html.erb (0.4ms)
+ Rendered examples/greet_hello.html.erb (0.2ms)
+ Rendered examples/form.html.erb (0.5ms)
+ Rendered examples/simple.html.erb within layouts/static (0.2ms)
@@ -0,0 +1,22 @@
+require 'spec_helper'
+require 'turning/file_storage'
+
+describe Turning::FileStorage do
+ it 'returns the content of a file from the filesystem' do
+ root = Rails.root.join('public', 'static')
+ putter = Turning::FileStorage.new(root)
+ getter = Turning::FileStorage.new(root)
+
+ putter.put('examples/awesomeness.html', 'awesome!')
+ results = getter.get('examples/awesomeness.html')
+
+ results.should == 'awesome!'
+ end
+
+ it 'returns nil for a file that does not exist' do
+ root = Rails.root.join('public', 'static')
+ getter = Turning::FileStorage.new(root)
+
+ getter.get('snakes').should be_nil
+ end
+end
@@ -2,6 +2,8 @@
require 'turning'
describe Turning do
+ include Rack::Test::Methods
+
it 'listens to events and renders the view to a static file' do
controller_class = Class.new(Turning::Controller) do
def initialize(renderer, model)
@@ -35,6 +37,11 @@ def trigger_update
controller.listen
model.trigger_update
- read_cached_view('examples/index.html').should == 'Hello'
+ get '/examples/index.html'
+ last_response.body.should == 'Hello'
+ end
+
+ def app
+ TestApp::Application
end
end
@@ -7,15 +7,15 @@
renderer = Turning::Renderer.new('examples')
renderer.render_to_file('say_hello', greeting: 'Hello')
- read_cached_view('examples/say_hello.html').should include 'Hello'
+ read_static_view('examples/say_hello.html').should include 'Hello'
end
it 'supplies built-in helpers' do
create_view('examples/go_home.html.erb', '<%= link_to "go home", root_path %>')
renderer = Turning::Renderer.new('examples')
renderer.render_to_file('go_home', {})
- read_cached_view('examples/go_home.html').should match(%r{<a href=".*">go home</a>})
+ read_static_view('examples/go_home.html').should match(%r{<a href=".*">go home</a>})
end
it 'supplies custom helpers' do
@@ -30,7 +30,7 @@ def greet
renderer = Turning::Renderer.new('examples')
renderer.render_to_file('greet_hello', {})
- read_cached_view('examples/greet_hello.html').should include 'Hello'
+ read_static_view('examples/greet_hello.html').should include 'Hello'
end
it 'disables forgery protection for static forms' do
@@ -45,6 +45,6 @@ def greet
renderer = Turning::Renderer.new('examples')
renderer.render_to_file('simple', {})
- read_cached_view('examples/simple.html').should == 'Check this: Hello'
+ read_static_view('examples/simple.html').should == 'Check this: Hello'
end
end
@@ -0,0 +1,31 @@
+require 'spec_helper'
+require 'turning/static_cascade'
+
+describe Turning::StaticCascade do
+ it 'serves the file if it exists' do
+ app = stub('app')
+ fake_content_storage = stub('fake content storage', get: 'contents')
+ static_file_name = '/ponies'
+ static_cascade = Turning::StaticCascade.new(app, fake_content_storage)
+
+ response = static_cascade.call('PATH_INFO' => static_file_name)
+ fake_content_storage.should have_received(:get).with(static_file_name)
+ response.should == [
+ 200,
+ { 'Content-Type' => 'text/html', 'Content-Length' => 'contents'.size.to_s },
+ ['contents']
+ ]
+ end
+
+ it 'cascades if the file does not exist' do
+ app = stub('app', call: 'app response')
+ fake_content_storage = stub('fake content storage', get: nil)
+ env = { 'PATH_INFO' => '/ponies' }
+ static_cascade = Turning::StaticCascade.new(app, fake_content_storage)
+
+ response = static_cascade.call(env)
+
+ app.should have_received(:call).with(env)
+ response.should == 'app response'
+ end
+end
View
@@ -22,4 +22,5 @@ Gem::Specification.new do |gem|
gem.add_development_dependency 'rake'
gem.add_development_dependency 'bourne'
gem.add_development_dependency 'tzinfo'
+ gem.add_development_dependency 'rack-test'
end

0 comments on commit dc9a2d7

Please sign in to comment.