Skip to content

Commit

Permalink
Rendering refactoring with layouts
Browse files Browse the repository at this point in the history
  • Loading branch information
Blake Mizerany committed Oct 1, 2007
1 parent e1b03fb commit ca5f8f3
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 92 deletions.
72 changes: 72 additions & 0 deletions lib/sinatra/context.rb
@@ -0,0 +1,72 @@
require File.dirname(__FILE__) + '/context/renderer'

module Sinatra

class EventContext

cattr_accessor :logger
attr_reader :request

include Sinatra::Renderer

def initialize(request)
@request = request
@headers = {}
end

def status(value = nil)
@status = value if value
@status || 200
end

def body(value = nil, &block)
@body = value if value
@body = block.call if block
@body
end

def error(value = nil)
if value
status 500
@error = value
erb :error, :views_directory => SINATRA_ROOT + '/files/'
end
@error
end

# This allows for:
# header 'Content-Type' => 'text/html'
# header 'Foo' => 'Bar'
# or
# headers 'Content-Type' => 'text/html',
# 'Foo' => 'Bar'
#
# Whatever blows your hair back
def headers(value = nil)
@headers.merge!(value) if value
@headers
end
alias :header :headers

def session
request.env['rack.session']
end

def params
@params ||= @request.params.symbolize_keys
end

def redirect(path)
logger.info "Redirecting to: #{path}"
status 302
header 'Location' => path
end

def log_event
logger.info "#{request.request_method} #{request.path_info} | Status: #{status} | Params: #{params.inspect}"
logger.exception(error) if error
end

end

end
38 changes: 38 additions & 0 deletions lib/sinatra/context/renderer.rb
@@ -0,0 +1,38 @@
Layouts = Hash.new

module Sinatra

module Renderer

DEFAULT_OPTIONS = {
:views_directory => 'views',
:layout => :layout
}

def render(template, renderer, options = {})
options = DEFAULT_OPTIONS.merge(options)

layout = block_given? ? yield : Layouts[options[:layout]]

result_method = 'render_%s' % renderer

if layout
send(result_method, layout) { send(result_method, determine_template(template, renderer, options)) }
else
send(result_method, determine_template(template, renderer, options))
end
end

protected

def determine_template(template, ext, options)
if template.is_a?(Symbol)
File.read("%s/%s.%s" % [options[:views_directory], template, ext])
else
template
end
end

end

end
15 changes: 15 additions & 0 deletions lib/sinatra/core_ext/metaid.rb
@@ -0,0 +1,15 @@
class Object
# The hidden singleton lurks behind everyone
def metaclass; class << self; self; end; end
def meta_eval &blk; metaclass.instance_eval &blk; end

# Adds methods to a metaclass
def meta_def name, &blk
meta_eval { define_method name, &blk }
end

# Defines an instance method within a class
def class_def name, &blk
class_eval { define_method name, &blk }
end
end
85 changes: 2 additions & 83 deletions lib/sinatra/event.rb
Expand Up @@ -28,98 +28,17 @@ def present_error
def not_found def not_found
Event.new(:get, 'not_found', false) do Event.new(:get, 'not_found', false) do
status 404 status 404
views_dir SINATRA_ROOT + '/files'


if request.path_info == '/' && request.request_method == 'GET' if request.path_info == '/' && request.request_method == 'GET'
erb :default_index erb :default_index, :views_directory => SINATRA_ROOT + '/files'
else else
erb :not_found erb :not_found, :views_directory => SINATRA_ROOT + '/files'
end end
end end
end end


end end

class EventContext

cattr_accessor :logger

attr_reader :request

def initialize(request)
@request = request
@headers = {}
end

def status(value = nil)
@status = value if value
@status || 200
end


def body(value = nil, &block)
@body = value if value
@body = block.call if block
@body
end

def error(value = nil)
if value
status 500
@error = value
views_dir SINATRA_ROOT + '/files/'
erb :error
end
@error
end

# This allows for:
# header 'Content-Type' => 'text/html'
# header 'Foo' => 'Bar'
# or
# headers 'Content-Type' => 'text/html',
# 'Foo' => 'Bar'
#
# Whatever blows your hair back
def headers(value = nil)
@headers.merge!(value) if value
@headers
end
alias :header :headers

def session
request.env['rack.session']
end

def params
@params ||= @request.params.symbolize_keys
end

def views_dir(value = nil)
@views_dir = value if value
@views_dir || File.dirname($0) + '/views'
end

def redirect(path)
logger.info "Redirecting to: #{path}"
status 302
header 'Location' => path
end

def determine_template(content, ext)
if content.is_a?(Symbol)
File.read("%s/%s.%s" % [views_dir, content, ext])
else
content
end
end

def log_event
logger.info "#{request.request_method} #{request.path_info} | Status: #{status} | Params: #{params.inspect}"
logger.exception(error) if error
end

end

class Event class Event


cattr_accessor :logger cattr_accessor :logger
Expand Down
47 changes: 47 additions & 0 deletions test/sinatra/renderer_test.rb
@@ -0,0 +1,47 @@
require File.dirname(__FILE__) + '/../helper'

class Sinatra::EventContext

def render_foo(template)
require 'erb'
ERB.new(template).result(binding)
end

end

describe "Renderer" do

before(:each) do
Layouts.clear
@context = Sinatra::EventContext.new(stub())
end

it "should render render a tempalate" do
@context.render('foo', :foo).should.equal 'foo'
end

it "should render with a layout if given" do
result = @context.render('content', :foo) do
'X <%= yield %> X'
end

result.should.equal 'X content X'
end

it "should render default layout if it exists and layout if no layout name given" do
Layouts[:layout] = 'X <%= yield %> Y'
@context.render('foo', :foo).should.equal 'X foo Y'

Layouts[:foo] = 'Foo <%= yield %> Layout'
@context.render('bar', :foo, :layout => :foo).should.equal 'Foo bar Layout'
end

it "should read template from a file if exists" do
File.expects(:read).with('views/bar.foo').returns('foo content')
@context.render(:bar, :foo).should.equal 'foo content'

File.expects(:read).with('views2/bar.foo').returns('foo content')
@context.render(:bar, :foo, :views_directory => 'views2').should.equal 'foo content'
end

end
2 changes: 1 addition & 1 deletion vendor/erb/init.rb
@@ -1,3 +1,3 @@
require File.dirname(__FILE__) + '/lib/erb' require File.dirname(__FILE__) + '/lib/erb'


Sinatra::EventContext.send(:include, Sinatra::Erb::InstanceMethods) Sinatra::EventContext.send(:include, Sinatra::Erb::EventContext)
9 changes: 6 additions & 3 deletions vendor/erb/lib/erb.rb
Expand Up @@ -2,13 +2,16 @@ module Sinatra


module Erb module Erb


module InstanceMethods module EventContext


def erb(content) def render_erb(content)
require 'erb' require 'erb'
body ERB.new(determine_template(content, :erb)).result(binding) body ERB.new(content).result(binding)
end end


def erb(template, options = {}, &layout)
render(template, :erb, options, &layout)
end
end end


end end
Expand Down
2 changes: 1 addition & 1 deletion vendor/haml/init.rb
@@ -1,3 +1,3 @@
require File.dirname(__FILE__) + '/lib/haml' require File.dirname(__FILE__) + '/lib/haml'


Sinatra::EventContext.send(:include, Sinatra::Haml::InstanceMethods) Sinatra::EventContext.send(:include, Sinatra::Haml::EventContext)
11 changes: 7 additions & 4 deletions vendor/haml/lib/haml.rb
Expand Up @@ -2,13 +2,16 @@ module Sinatra


module Haml module Haml


module InstanceMethods module EventContext


def haml(content) def render_haml(content)
require 'haml' require 'haml'
body ::Haml::Engine.new(determine_template(content, :haml)).render(self) body ::Haml::Engine.new(content).render(self)
end end


def haml(template, options = {}, &layout)
render(template, :haml, options, &layout)
end
end end


end end
Expand Down

0 comments on commit ca5f8f3

Please sign in to comment.