aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGibheer <gibheer@gmail.com>2013-02-27 22:27:02 +0100
committerGibheer <gibheer@gmail.com>2013-02-27 22:27:02 +0100
commit7fd2f6b25b2abd48a7292f7598e53ebd357e24f7 (patch)
tree3dc4c831b47ea36ac0682248d1305a52c82b3a45
parent714c540e4b40c931be365d12c31bbe9cbdfa5fb9 (diff)
reworked the renderer
The renderer is now a bit smaller and asks the TemplateFinder for the actual resources. That way it can just concentrate on rendering instead of finding out, which stuff actually exists and which not.
-rw-r--r--lib/zero/renderer.rb85
-rw-r--r--spec/fixtures/templates/special_layout.html.erb3
-rw-r--r--spec/unit/zero/renderer/initialize_spec.rb11
-rw-r--r--spec/unit/zero/renderer/read_template_path_bang_spec.rb16
-rw-r--r--spec/unit/zero/renderer/render_spec.rb71
-rw-r--r--spec/unit/zero/renderer/template_path.rb8
-rw-r--r--spec/unit/zero/renderer/templates_spec.rb13
-rw-r--r--spec/unit/zero/renderer/type_map_spec.rb13
8 files changed, 106 insertions, 114 deletions
diff --git a/lib/zero/renderer.rb b/lib/zero/renderer.rb
index 2a848c2..f1930ea 100644
--- a/lib/zero/renderer.rb
+++ b/lib/zero/renderer.rb
@@ -24,77 +24,68 @@ module Zero
# This type map is used to extend the possible renderings for different
# types, which the clients sends.
#
- # @example create a simple renderer
- # Renderer.new('app/templates')
+ # @example create a simple renderer with a mapping from html to text/html
+ # Renderer.new('app/templates', {'html' => 'text/html'})
#
# @example create a renderer with a small map
# Renderer.new('app', {
# 'html' => ['text/html', 'application/html+xml'],
# 'json' => ['application/json', 'application/aweomse+json']
# })
+ # @example create a renderer with a specific layout
+ # Renderer.new('app'. 'layouts/layout', {'html' => 'text/html'})
#
- # @param template_path [String] a string to templates
- # @param type_map [Hash] a map of simple types to complex ones
- def initialize(template_path, type_map = {})
- @template_path = template_path
- @type_map = type_map
+ # @param path [String] the relative path to templates
+ # @param layout [String] the key of the layouts
+ # @param types [Hash{String => Array}] a map of short type names to long ones
+ def initialize(path, layout = 'layout', types)
+ @path = path
+ @layout = layout
+ @types = types
end
# returns the hash of type conversions
# @return [Hash] type conversion
- attr_reader :type_map
+ attr_reader :types
+ # returns the key for layout files
+ # @return [String] the key for layouts
+ attr_reader :layout
# get the path to the templates
# @return [String] the base template path
- attr_reader :template_path
+ attr_reader :path
# get the tree of templates
+ #
+ # This function returns all templates with their keys.
# @api private
# @return [Hash] the template tree
- attr_reader :templates
-
- # load the template tree
- #
- # This method gets all templates in the `template_path` and builds an
- # internal tree structure, where templates and types direct the request to
- # the wanted template.
- # @return [Self] returns the object
- def read_template_path!
- @templates = TemplateFinder.new(template_path, @type_map).get_templates
+ def templates
+ @templates ||= TemplateFinder.new(path, types)
end
# render a template
#
- # This method will render the given template, based on the type in the given
- # context.
- # @param name [String] the name of the template
- # @param type [Array] a list of accept types used to find the template
- # @param context [Object] the context in which to evaluate the template
- # @return [String] the rendered content
- def render(name, type, context)
- template(name, type).render(context)
+ # This method will render the template according to the requested types.
+ # @param template [String] the template to render
+ # @param types [Array<String>] a list of types requested to render
+ # @param context [Object] any object to use for rendering
+ # @return [String] the result of rendering
+ def render(template, types, context)
+ unless templates.exist_for_types?(layout, types)
+ return load_template(template, types).render(context)
+ end
+ load_layout_template(types).render(context) do
+ load_template(template, types).render(context)
+ end
end
private
- # get the prepared template for the name and type
- # @api private
- # @param name [String] the name of the template
- # @param types [Array] the types for the template
- # @return [Tilt::Template] a prepared tilt template
- def template(name, types)
- if templates.has_key? name
- types.each do |type|
- template = templates[name][type]
- unless template.nil?
- # TODO Will be implemented later
- # return template if template.kind_of?(Tilt::Template)
- return Tilt.new(template)
- end
- end
- raise ArgumentError.new(
- "No template found for any of this types #{types.join ', '}!"
- )
- end
- raise ArgumentError.new "No template found for '#{name}'!"
+ def load_template(template, types)
+ templates.get(template, types)
+ end
+
+ def load_layout_template(types)
+ templates.get(layout, types)
end
end
end
diff --git a/spec/fixtures/templates/special_layout.html.erb b/spec/fixtures/templates/special_layout.html.erb
new file mode 100644
index 0000000..4288509
--- /dev/null
+++ b/spec/fixtures/templates/special_layout.html.erb
@@ -0,0 +1,3 @@
+special layout loaded
+
+<%= yield %>
diff --git a/spec/unit/zero/renderer/initialize_spec.rb b/spec/unit/zero/renderer/initialize_spec.rb
new file mode 100644
index 0000000..39d7302
--- /dev/null
+++ b/spec/unit/zero/renderer/initialize_spec.rb
@@ -0,0 +1,11 @@
+require 'spec_helper'
+
+describe Zero::Renderer, '#initialize' do
+ subject { described_class.new(template_path, type_map) }
+ let(:template_path) { 'foo/' }
+ let(:type_map) { {'html' => ['text/html'] } }
+
+ its(:path) { should be(template_path) }
+ its(:layout) { should match(/layout/) }
+ its(:types) { should be(type_map) }
+end
diff --git a/spec/unit/zero/renderer/read_template_path_bang_spec.rb b/spec/unit/zero/renderer/read_template_path_bang_spec.rb
deleted file mode 100644
index 9a2f875..0000000
--- a/spec/unit/zero/renderer/read_template_path_bang_spec.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-require 'spec_helper'
-
-describe Zero::Renderer, '#read_template_path!' do
- subject { Zero::Renderer.new(template_path, type_map) }
- let(:template_path) { 'spec/fixtures/templates/' }
- let(:type_map) { {'html' => ['text/html']} }
- let(:result) { {
- 'text/html' => template_path + 'index.html.erb',
- 'json' => template_path + 'index.json.erb'
- } }
-
- it "loads the templates" do
- subject.read_template_path!
- expect(subject.templates['index']).to eq(result)
- end
-end
diff --git a/spec/unit/zero/renderer/render_spec.rb b/spec/unit/zero/renderer/render_spec.rb
index 3270ac3..ed11857 100644
--- a/spec/unit/zero/renderer/render_spec.rb
+++ b/spec/unit/zero/renderer/render_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Zero::Renderer, '#render' do
- subject { Zero::Renderer.new(template_path, type_map) }
+ subject { described_class.new(template_path, type_map) }
let(:template_path) { 'spec/fixtures/templates/' }
let(:type_map) {{
'html' => ['text/html', 'text/xml', '*/*'],
@@ -12,43 +12,54 @@ describe Zero::Renderer, '#render' do
let(:foo_types) { ['foo/bar', 'bar/foo'] }
let(:binding) { SpecTemplateContext.new('foo') }
- before :each do
- subject.read_template_path!
- end
+ context 'with default layout' do
+ it 'returns a tilt template' do
+ subject.render('index', html_types, binding).should be_kind_of(String)
+ end
- it 'returns a tilt template' do
- subject.render('index', html_types, binding).should be_kind_of(String)
- end
+ it 'renders html content' do
+ subject.render('index', html_types, binding).should match('success')
+ end
- it 'renders html content' do
- subject.render('index', html_types, binding).should match('success')
- end
+ it 'returns a tilt template for different types' do
+ subject.render('index', json_types, binding).should be_kind_of(String)
+ end
- it 'returns a tilt template for different types' do
- subject.render('index', json_types, binding).should be_kind_of(String)
- end
+ it 'renders json content' do
+ subject.render('index', json_types, binding).should match("{text: 'success'}")
+ end
- it 'renders json content' do
- subject.render('index', json_types, binding).should match("{text: 'success'}")
- end
+ it 'returns an ArgumentError, if given template does not exist' do
+ expect {
+ subject.render('foobar', html_types, binding)
+ }.to raise_error(ArgumentError, /Template 'foobar' does not exist/)
+ end
- it 'returns an ArgumentError, if given template does not exist' do
- expect {
- subject.render('foobar', html_types, binding)
- }.to raise_error(ArgumentError, "No template found for 'foobar'!")
- end
+ it 'returns an ArgumentError, if no template fits types' do
+ expect {
+ subject.render('index', foo_types, binding)
+ }.to raise_error(
+ ArgumentError, /Template 'index' not found/)
+ end
- it 'returns an ArgumentError, if no template fits types' do
- expect {
- subject.render('index', foo_types, binding)
- }.to raise_error(
- ArgumentError,
- "No template found for any of this types #{foo_types.join ', '}!"
- )
+ it 'uses the context' do
+ subject.render('context', html_types, binding).should match('foo')
+
+ end
end
- it 'uses the context' do
- subject.render('context', html_types, binding).should match('foo')
+ context 'with special layout' do
+ subject { described_class.new(template_path, layout, type_map) }
+ let(:layout) { 'special_layout' }
+
+ it 'uses the layout for rendering' do
+ expect(subject.render('index', html_types, binding)
+ ).to match(/layout loaded/)
+ end
+ it 'renders the template into the layout' do
+ expect(subject.render('index', html_types, binding)
+ ).to match(/success/)
+ end
end
end
diff --git a/spec/unit/zero/renderer/template_path.rb b/spec/unit/zero/renderer/template_path.rb
deleted file mode 100644
index 261faa8..0000000
--- a/spec/unit/zero/renderer/template_path.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-require 'spec_helper'
-
-describe Zero::Renderer, '#template_path' do
- subject { Zero::Renderer.new(template_path) }
- let(:template_path) { 'foo' }
-
- its(:type_map) { should be(template_path) }
-end
diff --git a/spec/unit/zero/renderer/templates_spec.rb b/spec/unit/zero/renderer/templates_spec.rb
new file mode 100644
index 0000000..f86961b
--- /dev/null
+++ b/spec/unit/zero/renderer/templates_spec.rb
@@ -0,0 +1,13 @@
+require 'spec_helper'
+
+describe Zero::Renderer, '#templates' do
+ let(:object) { described_class.new(template_path, types) }
+ subject { object.templates }
+
+ let(:template_path) { 'spec/fixtures/templates/' }
+ let(:types) { {'html' => ['text/html']} }
+
+ it 'loads the template tree' do
+ expect(subject).to be_kind_of(Zero::Renderer::TemplateFinder)
+ end
+end
diff --git a/spec/unit/zero/renderer/type_map_spec.rb b/spec/unit/zero/renderer/type_map_spec.rb
deleted file mode 100644
index 290e579..0000000
--- a/spec/unit/zero/renderer/type_map_spec.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'spec_helper'
-
-describe Zero::Renderer, '#type_map' do
- subject { Zero::Renderer.new(template_path, type_map) }
- let(:template_path) { 'foo' }
- let(:type_map) { {'html' => ['text/html']} }
-
- its(:type_map) { should be(type_map) }
-
- it 'returns an empty Hash, if type_map is not set while initialization' do
- Zero::Renderer.new(template_path).type_map.should eq({})
- end
-end