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 * Extend `sinatra-content-for` to support Liquid, Radius, Markaby, Nokogiri and
Builder. At least the first two probably involve patching Tilt. 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/base'
require 'sinatra/decompile' require 'sinatra/decompile'
@ -6,21 +7,32 @@ module Sinatra
def self.new(base, pattern, conditions = {}, &block) def self.new(base, pattern, conditions = {}, &block)
Module.new do Module.new do
extend NamespacedMethods extend NamespacedMethods
include InstanceMethods
@base, @extensions = base, [] @base, @extensions = base, []
@pattern, @conditions = compile(pattern, conditions) @pattern, @conditions = compile(pattern, conditions)
@templates = Hash.new { |h,k| @base.templates[k] }
namespace = self namespace = self
before { extend namespace } before { extend(@namespace = namespace) }
define_method(:error_block!) do |*keys| class_eval(&block)
if block = keys.inject(nil) { |b,k| b ||= namespace.errors[k] } 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) instance_eval(&block)
else else
super(*keys) super
end end
end end
class_eval(&block)
end
end end
module SharedMethods module SharedMethods
@ -32,7 +44,7 @@ module Sinatra
module NamespacedMethods module NamespacedMethods
include SharedMethods include SharedMethods
include Sinatra::Decompile include Sinatra::Decompile
attr_reader :base attr_reader :base, :templates
def self.prefixed(*names) def self.prefixed(*names)
names.each { |n| define_method(n) { |*a, &b| prefixed(n, *a, &b) }} names.each { |n| define_method(n) { |*a, &b| prefixed(n, *a, &b) }}
@ -75,6 +87,30 @@ module Sinatra
@conditions[:provides] = args @conditions[:provides] = args
end 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 private
def app def app
@ -118,8 +154,7 @@ module Sinatra
end end
def method_missing(meth, *args, &block) def method_missing(meth, *args, &block)
return super if args.any? or block or not base.respond_to? meth base.send(meth, *args, &block)
base.send meth
end end
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 end
describe 'templates' do describe 'templates' do
it "allows to define nested templates" it "allows using templates from the base" do
it "allows to define nested layouts" mock_app do
it "allows setting a different views directory" 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 end
describe 'extensions' do describe 'extensions' do