Skip to content

Commit

Permalink
WIP: Allow customising error pages
Browse files Browse the repository at this point in the history
  • Loading branch information
twe4ked committed Jul 7, 2014
1 parent 19cd078 commit f76f55e
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/lotus/rendering_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def initialize(configuration)
@controller_pattern = %r{#{ configuration.controller_pattern.gsub(/\%\{(controller|action)\}/) { "(?<#{ $1 }>(.*))" } }}
@view_pattern = configuration.view_pattern
@namespace = configuration.namespace
@templates = configuration.templates
end

def render(response)
Expand Down
13 changes: 13 additions & 0 deletions lib/lotus/views/default.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@ class Default
def title
response[2].first
end

def render
status_code = response[0]
templates = Lotus::Application.configuration.templates

This comment has been minimized.

Copy link
@twe4ked

twe4ked Jul 11, 2014

Author Owner

Lotus::Application.configuration doesn't work here, it returns a default configuration. What's the best way to get the actual configuration.

This comment has been minimized.

Copy link
@jodosha

jodosha Jul 11, 2014

@twe4ked You can't from there.

If you look at the signature of a view's constructor it's: #initialize(template, locals). Lotus::View.render is also a factory: it instantiate a view, passing the right template.

What if we override it?

def self.render(root, template_name, context)
  if template = DefaultTemplateFinder.new(root, template_name).find
    new(template, context).render # the developer has defined a custom template
  else
    super(context) # render the default view
  end
end

..and

class Lotus::Views::DefaultTemplateFinder < Lotus::View::Rendering::TemplateFinder
  def initialize(root, template_name)
     @root = root
     @options = { template_name: template_name }
  end

  private
  def root
    @root
  end
end

.. to be used like:

# lib/lotus/rendering_policy.rb
Lotus::Views::Default.render(@templates, response.code, {response: response, format: :html})
template = "#{Pathname.new(templates).join(status_code.to_s)}.html.erb"

if File.exists?(template)
scope = Lotus::View::Rendering::Scope.new(self)
Lotus::View::Template.new(template).render scope
else
super
end
end
end
end
end
1 change: 1 addition & 0 deletions test/fixtures/one_file/404.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Custom 404 page
1 change: 1 addition & 0 deletions test/fixtures/one_file/500.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Custom 500 page
17 changes: 17 additions & 0 deletions test/fixtures/one_file/application.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
require 'tilt/erb'

module OneFile
class Application < Lotus::Application
configure do
routes do
get '/', to: 'dashboard#index'
get '/error', to: 'dashboard#error'
get '/four_hundred', to: 'dashboard#four_hundred'
end
end

Expand All @@ -17,5 +21,18 @@ def call(params)
self.body = 'Hello'
end
end

action 'Error' do
def call(params)
raise 'the roof'
end
end

action 'FourHundred' do
def call(params)
self.status = 400
self.body = 'Four Hundred'
end
end
end
end
50 changes: 50 additions & 0 deletions test/integration/error_page_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'test_helper'
require 'rack/test'
require 'fixtures/one_file/application'

describe 'Error page test' do
include Rack::Test::Methods

before do
@current_dir = Dir.pwd
Dir.chdir FIXTURES_ROOT.join('one_file')
@app = OneFile::Application.new
end

after do
Dir.chdir @current_dir
@current_dir = nil
end

def app
@app
end

def response
last_response
end

it 'returns custom error pages' do
get '/four_hundred'
response.status.must_equal 400
response.body.must_equal <<-EOF
<!DOCTYPE html>
<html>
<head>
<title>Four Hundred</title>
</head>
<body>
<h1>Four Hundred</h1>
</body>
</html>
EOF

get '/error'
response.status.must_equal 500
response.body.must_equal %(Custom 500 page\n)

get '/foo'
response.status.must_equal 404
response.body.must_equal %(Custom 404 page\n)
end
end

0 comments on commit f76f55e

Please sign in to comment.