1
0
Fork 0
mirror of https://github.com/sinatra/sinatra synced 2023-03-27 23:18:01 -04:00

add template support to namespaces

This commit is contained in:
Konstantin Haase 2011-03-29 10:08:05 +02:00
parent 961644dfca
commit 825c7e2412
5 changed files with 131 additions and 19 deletions

View file

@ -23,5 +23,3 @@
* Extend `sinatra-content-for` to support Liquid, Radius, Markaby, Nokogiri and
Builder. At least the first two probably involve patching Tilt.
* Have `sinatra-namespace` support namespace local templates.

View file

@ -1,3 +1,4 @@
require 'backports'
require 'sinatra/base'
require 'sinatra/decompile'
@ -6,23 +7,34 @@ module Sinatra
def self.new(base, pattern, conditions = {}, &block)
Module.new do
extend NamespacedMethods
@base, @extensions = base, []
include InstanceMethods
@base, @extensions = base, []
@pattern, @conditions = compile(pattern, conditions)
@templates = Hash.new { |h,k| @base.templates[k] }
namespace = self
before { extend namespace }
define_method(:error_block!) do |*keys|
if block = keys.inject(nil) { |b,k| b ||= namespace.errors[k] }
instance_eval(&block)
else
super(*keys)
end
end
before { extend(@namespace = namespace) }
class_eval(&block)
end
end
module InstanceMethods
def settings
@namespace
end
def template_cache
super.fetch(:nested, @namespace) { Tilt::Cache.new }
end
def error_block!(*keys)
if block = keys.inject(nil) { |b,k| b ||= @namespace.errors[k] }
instance_eval(&block)
else
super
end
end
end
module SharedMethods
def namespace(pattern, conditions = {}, &block)
Sinatra::Namespace.new(self, pattern, conditions, &block)
@ -32,7 +44,7 @@ module Sinatra
module NamespacedMethods
include SharedMethods
include Sinatra::Decompile
attr_reader :base
attr_reader :base, :templates
def self.prefixed(*names)
names.each { |n| define_method(n) { |*a, &b| prefixed(n, *a, &b) }}
@ -75,6 +87,30 @@ module Sinatra
@conditions[:provides] = args
end
def set(key, value = self, &block)
raise ArgumentError, "may not set #{key}" if key != :views
return key.each { |k,v| set(k, v) } if block.nil? and value == self
block ||= proc { value }
singleton_class.send(:define_method, key, &block)
end
def enable(*opts)
opts.each { |key| set(key, true) }
end
def disable(*opts)
opts.each { |key| set(key, false) }
end
def template(name, &block)
filename, line = caller_locations.first
templates[name] = [block, filename, line.to_i]
end
def layout(name=:layout, &block)
template name, &block
end
private
def app
@ -118,8 +154,7 @@ module Sinatra
end
def method_missing(meth, *args, &block)
return super if args.any? or block or not base.respond_to? meth
base.send meth
base.send(meth, *args, &block)
end
end

View file

@ -0,0 +1 @@
hi

View file

@ -0,0 +1 @@
ho

View file

@ -490,9 +490,86 @@ describe Sinatra::Namespace do
end
describe 'templates' do
it "allows to define nested templates"
it "allows to define nested layouts"
it "allows setting a different views directory"
it "allows using templates from the base" do
mock_app do
template(:foo) { 'hi' }
send(verb, '/') { erb :foo }
namespace '/foo' do
send(verb) { erb :foo }
end
end
if verb != :head
send(verb, '/').body.should == "hi"
send(verb, '/foo').body.should == "hi"
end
end
it "allows to define nested templates" do
mock_app do
template(:foo) { 'hi' }
send(verb, '/') { erb :foo }
namespace '/foo' do
template(:foo) { 'ho' }
send(verb) { erb :foo }
end
end
if verb != :head
send(verb, '/').body.should == "hi"
send(verb, '/foo').body.should == "ho"
end
end
it "allows to define nested layouts" do
mock_app do
layout { 'Hello <%= yield %>!' }
template(:foo) { 'World' }
send(verb, '/') { erb :foo }
namespace '/foo' do
layout { 'Hi <%= yield %>!' }
send(verb) { erb :foo }
end
end
if verb != :head
send(verb, '/').body.should == "Hello World!"
send(verb, '/foo').body.should == "Hi World!"
end
end
it "allows using templates from the base" do
mock_app do
layout { "he said: <%= yield %>" }
template(:foo) { 'hi' }
send(verb, '/') { erb :foo }
namespace '/foo' do
template(:foo) { 'ho' }
send(verb) { erb :foo }
end
end
if verb != :head
send(verb, '/').body.should == "he said: hi"
send(verb, '/foo').body.should == "he said: ho"
end
end
it "allows setting a different views directory" do
mock_app do
set :views, File.expand_path('../namespace', __FILE__)
send(verb, '/') { erb :foo }
namespace('/foo') do
set :views, File.expand_path('../namespace/nested', __FILE__)
send(verb) { erb :foo }
end
end
if verb != :head
send(verb, '/').body.should == "hi\n"
send(verb, '/foo').body.should == "ho\n"
end
end
end
describe 'extensions' do