0
module Merb::RenderMixin
0
# So we can do raise TemplateNotFound
0
include Merb::ControllerExceptions
0
# base<Module>:: Module that is including RenderMixin (probably a controller)
0
def self.included(base)
0
class_inheritable_accessor :_default_render_options
0
# Return the default render options.
0
def default_render_options
0
self._default_render_options ||= {}
0
# Set default render options at the class level.
0
def render_options(opts)
0
self._default_render_options = opts
0
# Set the default layout to use or nil/false to disable layout rendering.
0
- # This is a shortcut for render_options :layout => false.
0
+ # This is a shortcut for render_options :layout => false.
0
- # layout<~to_s>:: The layout that should be used for this class
0
+ # layout<~to_s>:: The layout that should be used for this class.
0
+ # You can override by passing :layout => true to render method.
0
# Hash:: The default render options.
0
self.default_render_options.update(:layout => (layout ? layout : false))
0
# Enable the default layout logic - reset the layout option.
0
self.default_render_options.delete(:layout)
0
# Render the specified item, with the specified options.
0
- # thing<String, Symbol, nil>::
0
+ # thing<String, Symbol, nil>::
0
# The thing to render. This will default to the current action
0
# opts<Hash>:: An options hash (see below)
0
# :format<Symbol>:: A registered mime-type format
0
# The path to the template relative to the template root
0
# The status to send to the client. Typically, this would be an integer
0
# (200), or a Merb status code (Accepted)
0
+ # :layout<~to_s
, FalseClass>::
0
# A layout to use instead of the default. This should be relative to the
0
# layout root. By default, the layout will be either the controller_name or
0
# application. If you want to use an alternative content-type than the one
0
# that the base template was rendered as, you will need to do :layout =>
0
- # "foo.#{content_type}" (i.e. "foo.json")
0
+ # "foo.#{content_type}" (i.e. "foo.json"). If you want to render without
0
+ # layout, use :layout => false. This overrides layout set by +layout+ method.
0
# String:: The rendered template, including layout, if appropriate.
0
# TemplateNotFound:: There is no template for the specified location.
0
# If you pass a Hash as the first parameter, it will be moved to opts and
0
# "thing" will be the current action
0
def render(thing = nil, opts = {})
0
# render :format => :xml means render nil, :format => :xml
0
opts, thing = thing, nil if thing.is_a?(Hash)
0
# Merge with class level default render options
0
opts = self.class.default_render_options.merge(opts)
0
# If you don't specify a thing to render, assume they want to render the current action
0
thing ||= action_name.to_sym
0
- opts[:format] ? (self.content_type = opts[:format]) : content_type
0
+ opts[:format] ? (self.content_type = opts[:format]) : content_type
0
# Handle options (:status)
0
- _handle_options!(opts)
0
+ _handle_options!(opts)
0
# Do we have a template to try to render?
0
if thing.is_a?(Symbol) || opts[:template]
0
template_method, template_location = _template_for(thing, content_type, controller_name, opts)
0
# Raise an error if there's no template
0
raise TemplateNotFound, "No template found at #{template_location}.*" \
0
unless template_method && self.respond_to?(template_method)
0
# Call the method in question and throw the content for later consumption by the layout
0
throw_content(:for_layout, self.send(template_method))
0
# Do we have a string to render?
0
elsif thing.is_a?(String)
0
# Throw it for later consumption by the layout
0
throw_content(:for_layout, thing)
0
# If we find a layout, use it. Otherwise, just render the content thrown for layout.
0
layout = opts[:layout] != false && _get_layout(opts[:layout])
0
layout ? send(layout) : catch_content(:for_layout)
0
# Renders an object using to registered transform method based on the
0
# negotiated content-type, if a template does not exist. For instance, if the
0
# content-type is :json, Merb will first look for current_action.json.*.
0
# Failing that, it will run object.to_json.
0
# An object that responds_to? the transform method registered for the
0
# negotiated mime-type.
0
# thing<String, Symbol>::
0
# The thing to attempt to render via #render before calling the transform
0
# method on the object. Defaults to nil.
0
# An options hash that will be used for rendering
0
# (passed on to #render or serialization methods like #to_json or #to_xml)
0
# The rendered template or if no template is found, the transformed object.
0
# If there is no transform method for the specified mime-type or the object
0
# does not respond to the transform method.
0
# A string in the second parameter will be interpreted as a template:
0
- # display @object, "path/to/foo"
0
+ # display @object, "path/to/foo"
0
# #=> display @object, nil, :template => "path/to/foo"
0
# A hash in the second parameters will be interpreted as opts:
0
# If you need to pass extra parameters to serialization method, for instance,
0
# to exclude some of attributes or serialize associations, just pass options
0
- # display
@locations, :except => [:locatable_type, :locatable_id], :include => [:locatable]
0
+ # display
@locations, :except => [:locatable_type, :locatable_id], :include => [:locatable]
0
- # serializes object with polymorphic association,
not raw locatable_* attributes.
0
+ # serializes object with polymorphic association,
not raw locatable_* attributes.
0
# :template a template to use for rendering
0
# :layout a layout to use for rendering
0
# all other options options that will be pass to serialization method
0
# like #to_json or #to_xml
0
# display @object, "path/to/foo" means display @object, nil, :template => "path/to/foo"
0
# display @object, :template => "path/to/foo" means display @object, nil, :template => "path/to/foo"
0
template_opt = opts.delete(:template)
0
template_opt, thing = thing, nil
0
opts, thing = thing, nil
0
# Try to render without the object
0
render(thing || action_name.to_sym, opts.merge(:template => template_opt))
0
# If the render fails (i.e. a template was not found)
0
rescue TemplateNotFound
0
# Merge with class level default render options
0
opts = self.class.default_render_options.merge(opts)
0
# Figure out what to transform and raise NotAcceptable unless there's a transform method assigned
0
transform = Merb.mime_transform_method(content_type)
0
raise NotAcceptable unless transform && object.respond_to?(transform)
0
# Only use a layout if one was specified
0
layout_opt = opts.delete(:layout)
0
# Look for the layout under the default layout directly. If it's not found, reraise
0
# the TemplateNotFound error
0
- template = _template_location(layout_opt, layout.index(".") ? content_type : nil, "layout")
0
+ template = _template_location(layout_opt, layout.index(".") ? content_type : nil, "layout")
0
layout = _template_for(_template_root / template) ||
0
- (raise TemplateNotFound, "No layout found at #{_template_root / template}.*")
0
+ (raise TemplateNotFound, "No layout found at #{_template_root / template}.*")
0
# If the layout was found, call it
0
# Otherwise, just render the transformed object
0
throw_content(:for_layout, object.send(transform, opts))
0
throw_content(:for_layout, object.send(transform))
0
catch_content(:for_layout)
0
- # The path to the template, relative to the current controller or the
0
+ # The path to the template, relative to the current controller or the
0
# template root. If the template contains a "/", Merb will search for it
0
# relative to the template root; otherwise, Merb will search for it
0
# relative to the current controller.
0
template = template.to_s
0
kontroller = (m = template.match(/.*(?=\/)/)) ? m[0] : controller_name
0
template = "_#{File.basename(template)}"
0
template_method, template_location = _template_for(template, opts.delete(:format) || content_type, kontroller)
0
(@_old_partial_locals ||= []).push @_merb_partial_locals
0
@_merb_partial_locals = opts
0
sent_template = [with].flatten.map do |temp|
0
@_merb_partial_locals[as.to_sym] = temp
0
+ if template_method && self.respond_to?(template_method)
0
+ raise TemplateNotFound, "Could not find template at #{template_location}.*"
0
@_merb_partial_locals = opts
0
@_merb_partial_locals = @_old_partial_locals.pop
0
# Take the options hash and handle it as appropriate.
0
# opts<Hash>:: The options hash that was passed into render.
0
# The status of the response will be set to opts[:status].to_i
0
# Hash:: The options hash that was passed in.
0
def _handle_options!(opts)
0
# opts<Hash>:: The options hash that was passed to the render
0
# Sets headers['Location'] to the provided URL
0
# Hash:: The options hash that was passed in.
0
def _handle_location!(opts)
0
# layout<~to_s>:: A layout, relative to the layout root. Defaults to nil.
0
# String:: The method name that corresponds to the found layout.
0
# If a layout was specified (either via layout in the class or by passing
0
def _get_layout(layout = nil)
0
layout = layout.instance_of?(Symbol) && self.respond_to?(layout, true) ? send(layout) : layout
0
layout = layout.to_s if layout
0
# If a layout was provided, throw an error if it's not found
0
template_method, template_location = _template_for(layout, layout.index(".") ? nil : content_type, "layout")
0
- # Iterate over the template roots in reverse order, and return the template
0
+ # Iterate over the template roots in reverse order, and return the template
0
# and template location of the first match.
0
# context<Object>:: The controller action or template basename.
0
- # content_type<~to_s>:: The content type
. Defaults to nil.
0
+ # content_type<~to_s>:: The content type
(like html or json).
0
# controller<~to_s>:: The name of the controller. Defaults to nil.
0
def _template_for(context, content_type, controller=nil, opts={})
0
template_location = nil
0
- self.class._template_roots.reverse_each do |root, template_location|
0
+ self.class._template_roots.reverse_each do |root, template_location|
0
if opts[:template] # use the given template as the location context
0
template_location = root / self.send(template_location, opts[:template], content_type, nil)
0
template_method = Merb::Template.template_for(template_location)
0
break if template_method && self.respond_to?(template_method)
0
template_location = root / (opts[:template] || self.send(template_location, context, content_type, controller))
0
template_method = Merb::Template.template_for(template_location)
0
break if template_method && self.respond_to?(template_method)
0
[template_method, template_location]
0
# Called in templates to get at content thrown in another template. The
0
# results of rendering a template are automatically thrown into :for_layout,
0
# so catch_content or catch_content(:for_layout) can be used inside layouts
0
def catch_content(obj = :for_layout)
0
# Called in templates to test for the existence of previously thrown content.
0
def thrown_content?(obj = :for_layout)
0
@_caught_content.key?(obj)
0
# Called in templates to store up content for later use. Takes a string
0
# and/or a block. First, the string is evaluated, and then the block is
0
# captured using the capture() helper provided by the template languages. The
0
@_caught_content[obj] = string.to_s << (block_given? ? capture(&block) : "")