mirror of
https://github.com/sinatra/sinatra
synced 2023-03-27 23:18:01 -04:00
Builder Rendering Helper (.builder templates) w/ doco and tests.
This commit is contained in:
parent
327c6ece36
commit
caf4857024
6 changed files with 200 additions and 1 deletions
|
@ -406,6 +406,97 @@ module Sinatra
|
|||
|
||||
end
|
||||
|
||||
# Generating conservative XML content using Builder templates.
|
||||
#
|
||||
# Builder templates can be inline by passing a block to the builder method, or in
|
||||
# external files with +.builder+ extension by passing the name of the template
|
||||
# to the +builder+ method as a Symbol.
|
||||
#
|
||||
# === Inline Rendering
|
||||
#
|
||||
# If the builder method is given a block, the block is called directly with an
|
||||
# +XmlMarkup+ instance and the result is returned as String:
|
||||
# get '/who.xml' do
|
||||
# builder do |xml|
|
||||
# xml.instruct!
|
||||
# xml.person do
|
||||
# xml.name "Francis Albert Sinatra",
|
||||
# :aka => "Frank Sinatra"
|
||||
# xml.email 'frank@capitolrecords.com'
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# Yields the following XML:
|
||||
# <?xml version='1.0' encoding='UTF-8'?>
|
||||
# <person>
|
||||
# <name aka='Frank Sinatra'>Francis Albert Sinatra</name>
|
||||
# <email>Frank Sinatra</email>
|
||||
# </person>
|
||||
#
|
||||
# === Builder Template Files
|
||||
#
|
||||
# Builder templates can be stored in separate files with a +.builder+
|
||||
# extension under the view path. An +XmlMarkup+ object named +xml+ is automatically
|
||||
# made available to template.
|
||||
#
|
||||
# Example:
|
||||
# get '/bio.xml' do
|
||||
# builder :bio
|
||||
# end
|
||||
#
|
||||
# The "views/bio.builder" file might contain the following:
|
||||
# xml.instruct! :xml, :version => '1.1'
|
||||
# xml.person do
|
||||
# xml.name "Francis Albert Sinatra"
|
||||
# xml.aka "Frank Sinatra"
|
||||
# xml.aka "Ol' Blue Eyes"
|
||||
# xml.aka "The Chairman of the Board"
|
||||
# xml.born 'date' => '1915-12-12' do
|
||||
# xml.text! "Hoboken, New Jersey, U.S.A."
|
||||
# end
|
||||
# xml.died 'age' => 82
|
||||
# end
|
||||
#
|
||||
# And yields the following output:
|
||||
# <?xml version='1.1' encoding='UTF-8'?>
|
||||
# <person>
|
||||
# <name>Francis Albert Sinatra</name>
|
||||
# <aka>Frank Sinatra</aka>
|
||||
# <aka>Ol' Blue Eyes</aka>
|
||||
# <aka>The Chairman of the Board</aka>
|
||||
# <born date='1915-12-12'>Hoboken, New Jersey, U.S.A.</born>
|
||||
# <died age='82' />
|
||||
# </person>
|
||||
#
|
||||
# NOTE: Builder must be installed or a LoadError will be raised the first time an
|
||||
# attempt is made to render a builder template.
|
||||
#
|
||||
# See http://builder.rubyforge.org/ for comprehensive documentation on Builder.
|
||||
module Builder
|
||||
|
||||
def builder(content=nil, options={}, &block)
|
||||
options, content = content, nil if content.is_a?(Hash)
|
||||
content = Proc.new { block } if content.nil?
|
||||
render(:builder, content, options)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_builder(content, &b)
|
||||
require 'builder'
|
||||
xml = ::Builder::XmlMarkup.new(:indent => 2)
|
||||
case content
|
||||
when String
|
||||
eval(content, binding, '<BUILDER>', 1)
|
||||
when Proc
|
||||
content.call(xml)
|
||||
end
|
||||
xml.target!
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class EventContext
|
||||
|
||||
include ResponseHelpers
|
||||
|
@ -413,6 +504,7 @@ module Sinatra
|
|||
include RenderingHelpers
|
||||
include Erb
|
||||
include Haml
|
||||
include Builder
|
||||
|
||||
attr_accessor :request, :response
|
||||
|
||||
|
|
101
test/builder_test.rb
Normal file
101
test/builder_test.rb
Normal file
|
@ -0,0 +1,101 @@
|
|||
require File.dirname(__FILE__) + '/helper'
|
||||
|
||||
context "Builder" do
|
||||
|
||||
setup do
|
||||
Sinatra.application = nil
|
||||
end
|
||||
|
||||
context "without layouts" do
|
||||
|
||||
setup do
|
||||
Sinatra.application = nil
|
||||
end
|
||||
|
||||
specify "should render" do
|
||||
|
||||
get '/no_layout' do
|
||||
builder 'xml.instruct!'
|
||||
end
|
||||
|
||||
get_it '/no_layout'
|
||||
should.be.ok
|
||||
body.should == %(<?xml version="1.0" encoding="UTF-8"?>\n)
|
||||
|
||||
end
|
||||
|
||||
specify "should render inline block" do
|
||||
|
||||
get '/no_layout_and_inlined' do
|
||||
@name = "Frank & Mary"
|
||||
builder do |xml|
|
||||
xml.couple @name
|
||||
end
|
||||
end
|
||||
|
||||
get_it '/no_layout_and_inlined'
|
||||
should.be.ok
|
||||
body.should == %(<couple>Frank & Mary</couple>\n)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
context "Templates (in general)" do
|
||||
|
||||
setup do
|
||||
Sinatra.application = nil
|
||||
end
|
||||
|
||||
specify "are read from files if Symbols" do
|
||||
|
||||
get '/from_file' do
|
||||
@name = 'Blue'
|
||||
builder :foo, :views_directory => File.dirname(__FILE__) + "/views"
|
||||
end
|
||||
|
||||
get_it '/from_file'
|
||||
should.be.ok
|
||||
body.should.equal %(<exclaim>You rock Blue!</exclaim>\n)
|
||||
|
||||
end
|
||||
|
||||
specify "use layout.ext by default if available" do
|
||||
|
||||
get '/' do
|
||||
builder :foo, :views_directory => File.dirname(__FILE__) + "/views/layout_test"
|
||||
end
|
||||
|
||||
get_it '/'
|
||||
should.be.ok
|
||||
body.should.equal "<layout>\n<this>is foo!</this>\n</layout>\n"
|
||||
|
||||
end
|
||||
|
||||
specify "renders without layout" do
|
||||
|
||||
get '/' do
|
||||
builder :no_layout, :views_directory => File.dirname(__FILE__) + "/views/no_layout"
|
||||
end
|
||||
|
||||
get_it '/'
|
||||
should.be.ok
|
||||
body.should.equal "<foo>No Layout!</foo>\n"
|
||||
|
||||
end
|
||||
|
||||
specify "raises error if template not found" do
|
||||
|
||||
get '/' do
|
||||
builder :not_found
|
||||
end
|
||||
|
||||
lambda { get_it '/' }.should.raise(Errno::ENOENT)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
1
test/views/foo.builder
Normal file
1
test/views/foo.builder
Normal file
|
@ -0,0 +1 @@
|
|||
xml.exclaim "You rock #{@name}!"
|
1
test/views/layout_test/foo.builder
Normal file
1
test/views/layout_test/foo.builder
Normal file
|
@ -0,0 +1 @@
|
|||
xml.this "is foo!"
|
3
test/views/layout_test/layout.builder
Normal file
3
test/views/layout_test/layout.builder
Normal file
|
@ -0,0 +1,3 @@
|
|||
xml.layout do
|
||||
xml << yield
|
||||
end
|
1
test/views/no_layout/no_layout.builder
Normal file
1
test/views/no_layout/no_layout.builder
Normal file
|
@ -0,0 +1 @@
|
|||
xml.foo "No Layout!"
|
Loading…
Reference in a new issue