Skip to content

Commit

Permalink
first crappy pass
Browse files Browse the repository at this point in the history
  • Loading branch information
joshbuddy committed Oct 19, 2011
1 parent 57e0fc4 commit 50aedbb
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 54 deletions.
80 changes: 37 additions & 43 deletions renee-render/lib/renee-render.rb
@@ -1,4 +1,5 @@
require 'tilt'
require 'callsite'

# Top-level Renee constant
class Renee
Expand All @@ -23,6 +24,11 @@ def render!(*args, &blk)
halt render(*args, &blk)
end

def render_inline!(*args, &blk)
args << Callsite.parse(caller.first)
halt render_inline(*args, &blk)
end

##
# Renders a string given the engine and the content.
#
Expand All @@ -39,9 +45,35 @@ def render!(*args, &blk)
#
# @api public
#
def render(engine, data=nil, options={}, &block)
# Handles the case where engine is unspecified by shifting the data (i.e render "index")
engine, data, options = nil, engine.to_sym, data if data.nil? || data.is_a?(Hash)
def render(*args, &block)
render_setup(args, block) do |engine, data, options, views|
template_cache.fetch(engine, data, options) do
file_path, engine = find_template(views, data, engine)
template = Tilt[engine]
raise TemplateNotFound, "Template engine not found: #{engine}" if template.nil?
raise TemplateNotFound, "Template '#{data}' not found in '#{engine}'!" unless file_path
# TODO suppress errors for layouts?
template.new(file_path, 1, options)
end
end
end # render

def render_inline(*args, &block)
call_data = args.last.is_a?(Callsite::Line) ? args.pop : Callsite.parse(caller.first)
path, line = call_data.filename, call_data.line
render_setup(args, block) do |engine, data, options, views|
body = data.is_a?(String) ? Proc.new { data } : data
template = Tilt[engine]
raise "Template engine not found: #{engine}" if template.nil?
template.new(path, line.to_i, options, &body)
end
end

def render_setup(args, block)
options = args.last.is_a?(Hash) ? args.pop : {}
data = args.pop
engine = args.pop
engine &&= engine.to_sym

options ||= {}
options[:outvar] ||= '@_out_buf'
Expand All @@ -56,54 +88,16 @@ def render(engine, data=nil, options={}, &block)
scope = options.delete(:scope) || self

# TODO default layout file convention?
template = compile_template(engine, data, options, views)
template = yield(engine, data, options, views)
output = template.render(scope, locals, &block)

if layout # render layout
# TODO handle when layout is missing better!
options = options.merge(:views => views, :layout => false, :scope => scope)
return render(layout_engine, layout, options.merge(:locals => locals)) { output }
end

output
end # render

##
# Constructs a template based on engine, data and options.
#
# @param [Symbol] engine The template engine to use for rendering.
# @param [String] data The content or file to render.
# @param [Hash] options The rendering options to pass onto tilt.
# @param [String] views The view_path from which to locate the template.
#
# @return [Tilt::Template] The tilt template to render with all required options.
# @raise [TemplateNotFound] The template to render could not be located.
# @raise [RenderError] The template to render could not be located.
#
# @api private
#
def compile_template(engine, data, options, views)
template_cache.fetch engine, data, options do
if data.is_a?(Symbol) # data is template path
file_path, engine = find_template(views, data, engine)
template = Tilt[engine]
raise TemplateNotFound, "Template engine not found: #{engine}" if template.nil?
raise TemplateNotFound, "Template '#{data}' not found in '#{views}'!" unless file_path
# TODO suppress errors for layouts?
template.new(file_path, 1, options)
elsif data.is_a?(String) # data is body string
# TODO figure out path based on caller file
path, line = options[:path] || "caller file", options[:line] || 1
body = data.is_a?(String) ? Proc.new { data } : data
template = Tilt[engine]
raise "Template engine not found: #{engine}" if template.nil?
template.new(path, line.to_i, options, &body)
else # data can't be handled
raise RenderError, "Cannot render data #{data.inspect}."
end
end # template_cache.fetch
end # compile_template

end
##
# Searches view paths for template based on data and engine with rendering options.
# Supports finding a template without an engine.
Expand Down
1 change: 1 addition & 0 deletions renee-render/renee-render.gemspec
Expand Up @@ -20,6 +20,7 @@ Gem::Specification.new do |s|

s.add_runtime_dependency 'rack', "~> 1.3.0"
s.add_runtime_dependency 'tilt', "~> 1.3.3"
s.add_runtime_dependency 'callsite', '~> 0.0.6'
s.add_development_dependency 'minitest', "~> 2.6.1"
s.add_development_dependency 'rake'
s.add_development_dependency 'bundler', "~> 1.0.10"
Expand Down
14 changes: 3 additions & 11 deletions renee-render/test/render_test.rb
Expand Up @@ -6,9 +6,9 @@

it "should allow rendering string with engine" do
mock_app {
path("/a") { get { render! :erb, "<p>test</p>" } }
path("/b") { get { render! :erb, "<p><%= foo %></p>", :locals => { :foo => "bar" } } }
path("/c") { get { halt render(:erb, "<p><%= foo %></p>", :locals => { :foo => "bar" }) } }
path("/a") { get { render_inline! :erb, "<p>test</p>" } }
path("/b") { get { render_inline! :erb, "<p><%= foo %></p>", :locals => { :foo => "bar" } } }
path("/c") { get { halt render_inline(:erb, "<p><%= foo %></p>", :locals => { :foo => "bar" }) } }
}
get('/a')
assert_equal 200, response.status
Expand Down Expand Up @@ -102,13 +102,5 @@
}
assert_raises(Renee::Render::TemplateNotFound) { get('/') }
end # missing template, with engine

it "should fail properly rendering invalid data" do
create_view :index, "%p test", :haml
mock_app {
get { render! :haml, /invalid regex data/ }
}
assert_raises(Renee::Render::RenderError) { get('/') }
end # missing template, with engine
end
end

0 comments on commit 50aedbb

Please sign in to comment.