From 4de90276a0b5dcfa42b8378fb2a2f1153087fb75 Mon Sep 17 00:00:00 2001 From: Ryan Tomayko Date: Thu, 26 Mar 2009 08:01:20 -0700 Subject: [PATCH] Better template inheritance --- lib/sinatra/base.rb | 28 +++++++++++++++++++--------- test/templates_test.rb | 23 +++++++++++++++++++++-- 2 files changed, 40 insertions(+), 11 deletions(-) diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb index a880741c..627f5dbe 100644 --- a/lib/sinatra/base.rb +++ b/lib/sinatra/base.rb @@ -270,23 +270,33 @@ module Sinatra def lookup_template(engine, template, views_dir, filename = nil, line = nil) case template when Symbol - if cached = self.class.templates[template] - lookup_template(engine, cached[:template], views_dir, cached[:filename], cached[:line]) - else - path = ::File.join(views_dir, "#{template}.#{engine}") - [ ::File.read(path), path, 1 ] - end + load_template(engine, template, views_dir, options) when Proc filename, line = self.class.caller_locations.first if filename.nil? - [ template.call, filename, line.to_i ] + [template.call, filename, line.to_i] when String filename, line = self.class.caller_locations.first if filename.nil? - [ template, filename, line.to_i ] + [template, filename, line.to_i] else raise ArgumentError end end + def load_template(engine, template, views_dir, options={}) + base = self.class + while base.respond_to?(:templates) + if cached = base.templates[template] + return lookup_template(engine, cached[:template], views_dir, cached[:filename], cached[:line]) + else + base = base.superclass + end + end + + # If no template exists in the cache, try loading from disk. + path = ::File.join(views_dir, "#{template}.#{engine}") + [ ::File.read(path), path, 1 ] + end + def lookup_layout(engine, template, views_dir) lookup_template(engine, template, views_dir) rescue Errno::ENOENT @@ -887,7 +897,7 @@ module Sinatra def reset!(base=superclass) @routes = {} - @templates = base.templates.dup + @templates = {} @conditions = [] @filters = [] @errors = base.errors.dup diff --git a/test/templates_test.rb b/test/templates_test.rb index d2febc91..7c9711c6 100644 --- a/test/templates_test.rb +++ b/test/templates_test.rb @@ -1,8 +1,8 @@ require File.dirname(__FILE__) + '/helper' class TemplatesTest < Test::Unit::TestCase - def render_app(&block) - mock_app { + def render_app(base=Sinatra::Base, &block) + mock_app(base) { def render_test(template, data, options, locals, &block) inner = block ? block.call : '' data + inner @@ -107,6 +107,25 @@ class TemplatesTest < Test::Unit::TestCase assert ok? assert_equal 'Hello Mike!

content

', body end + + it 'loads templates defined in subclasses' do + base = Class.new(Sinatra::Base) + base.template(:foo) { 'bar' } + render_app(base) { render :test, :foo } + assert ok? + assert_equal 'bar', body + end + + it 'uses templates in superclasses before subclasses' do + base = Class.new(Sinatra::Base) + base.template(:foo) { 'template in superclass' } + render_app(base) { render :test, :foo } + @app.template(:foo) { 'template in subclass' } + + get '/' + assert ok? + assert_equal 'template in subclass', body + end end # __END__ : this is not the real end of the script.