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:
parent
961644dfca
commit
825c7e2412
5 changed files with 131 additions and 19 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
1
sinatra-contrib/spec/namespace/foo.erb
Normal file
1
sinatra-contrib/spec/namespace/foo.erb
Normal file
|
@ -0,0 +1 @@
|
|||
hi
|
1
sinatra-contrib/spec/namespace/nested/foo.erb
Normal file
1
sinatra-contrib/spec/namespace/nested/foo.erb
Normal file
|
@ -0,0 +1 @@
|
|||
ho
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue