module Roda::RodaPlugins::Render::InstanceMethods
def _cached_template_method(template)
method symbol. This optimization is only used for render/view calls
If there is an instance method for the template, return the instance
def _cached_template_method(template) case template when String, Symbol if (method_cache = render_opts[:template_method_cache]) _cached_template_method_lookup(method_cache, template) end end end
def _cached_template_method(_)
def _cached_template_method(_) nil end
def _cached_template_method_key(template)
def _cached_template_method_key(template) template end
def _cached_template_method_key(_)
def _cached_template_method_key(_) nil end
def _cached_template_method_lookup(method_cache, template)
def _cached_template_method_lookup(method_cache, template) method_cache[template] end
def _layout_method
def _layout_method self.class.opts[:render][:template_method_cache][:_roda_layout] end
def _layout_method
def _layout_method nil end
def _optimized_render_method_for_locals(template, locals)
of the template render if the optimized path is used, or nil if the optimized
Use an optimized render path for templates with a hash of locals. Returns the result
def _optimized_render_method_for_locals(template, locals) return unless method_cache = render_opts[:template_method_cache] locals_keys = locals.keys.sort key = [:_render_locals, template, locals_keys] optimized_template = case template when String, Symbol _cached_template_method_lookup(method_cache, key) else return end case optimized_template when Symbol optimized_template else if method_cache_key = _cached_template_method_key(key) template_obj = retrieve_template(render_template_opts(template, NO_CACHE)) method_name = :"_roda_template_locals_#{self.class.object_id}_#{method_cache_key}" method_cache[method_cache_key] = case template_obj when Render::TemplateMtimeWrapper template_obj.define_compiled_method(self.class, method_name, locals_keys) else begin unbound_method = Render.tilt_template_compiled_method(template_obj, locals_keys, self.class) rescue ::NotImplementedError false else self.class::RodaCompiledTemplates.send(:define_method, method_name, unbound_method) self.class::RodaCompiledTemplates.send(:private, method_name) method_name end end end end end
def _optimized_render_method_for_locals(_, _)
def _optimized_render_method_for_locals(_, _) nil end
def _optimized_view_content(template)
Get the content for #view, or return nil to use the unoptimized approach. Only called if
def _optimized_view_content(template) if optimized_template = _cached_template_method(template) send(optimized_template, OPTS) elsif template.is_a?(Hash) && template.length == 1 template[:content] end end
def _optimized_view_content(template)
def _optimized_view_content(template) nil end
def cached_template(opts, &block)
If caching templates, attempt to retrieve the template from the cache. Otherwise, just yield
def cached_template(opts, &block) if key = opts[:cache_key] cache = render_opts[:cache] unless template = cache[key] template = cache[key] = yield end template else yield end end
def find_template(opts)
Given the template name and options, set the template class, template path/content,
def find_template(opts) render_opts = self.class.opts[:render] engine_override = opts[:engine] engine = opts[:engine] ||= render_opts[:engine] if content = opts[:inline] path = opts[:path] = content template_class = opts[:template_class] ||= ::Tilt[engine] opts[:template_block] = self.class.inline_template_block(content) else opts[:views] ||= render_opts[:views] path = opts[:path] ||= template_path(opts) template_class = opts[:template_class] opts[:template_class] ||= ::Tilt end if (cache = opts[:cache]).nil? cache = content || !opts[:template_block] end if cache unless opts.has_key?(:cache_key) template_block = opts[:template_block] unless content template_opts = opts[:template_opts] opts[:cache_key] = if template_class || engine_override || template_opts || template_block [path, template_class, engine_override, template_opts, template_block] else path end end else opts.delete(:cache_key) end opts end
def parse_template_opts(template, opts)
def parse_template_opts(template, opts) opts = Hash[opts] if template.is_a?(Hash) opts.merge!(template) else if opts.empty? && (key = _cached_template_method_key(template)) opts[:template_method_cache_key] = key end opts[:template] = template opts end end
def render(template, opts = (no_opts = true; optimized_template = _cached_template_method(template); OPTS), &block)
def render(template, opts = (no_opts = true; optimized_template = _cached_template_method(template); OPTS), &block) if optimized_template send(optimized_template, OPTS, &block) elsif !no_opts && opts.length == 1 && (locals = opts[:locals]) && (optimized_template = _optimized_render_method_for_locals(template, locals)) send(optimized_template, locals, &block) else opts = render_template_opts(template, opts) retrieve_template(opts).render((opts[:scope]||self), (opts[:locals]||OPTS), &block) end end
def render_layout_opts
The default render options to use. These set defaults that can be overridden by
def render_layout_opts Hash[render_opts[:layout_opts]] end
def render_opts
def render_opts self.class.render_opts end
def render_template_opts(template, opts)
def render_template_opts(template, opts) parse_template_opts(template, opts) end
def retrieve_template(opts)
def retrieve_template(opts) cache = opts[:cache] if !opts[:cache_key] || cache == false found_template_opts = opts = find_template(opts) end cached_template(opts) do opts = found_template_opts || find_template(opts) render_opts = self.class.opts[:render] template_opts = render_opts[:template_opts] if engine_opts = render_opts[:engine_opts][opts[:engine]] template_opts = template_opts.merge(engine_opts) end if current_template_opts = opts[:template_opts] template_opts = template_opts.merge(current_template_opts) end define_compiled_method = COMPILED_METHOD_SUPPORT && (method_cache_key = opts[:template_method_cache_key]) && (method_cache = render_opts[:template_method_cache]) && (method_cache[method_cache_key] != false) && !opts[:inline] if render_opts[:check_template_mtime] && !opts[:template_block] && !cache template = TemplateMtimeWrapper.new(self.class, opts, template_opts) if define_compiled_method method_name = :"_roda_template_#{self.class.object_id}_#{method_cache_key}" method_cache[method_cache_key] = template.define_compiled_method(self.class, method_name) end else template = self.class.create_template(opts, template_opts) if define_compiled_method && cache != false begin unbound_method = Render.tilt_template_compiled_method(template, EMPTY_ARRAY, self.class) rescue ::NotImplementedError method_cache[method_cache_key] = false else method_name = :"_roda_template_#{self.class.object_id}_#{method_cache_key}" self.class::RodaCompiledTemplates.send(:define_method, method_name, unbound_method) self.class::RodaCompiledTemplates.send(:private, method_name) method_cache[method_cache_key] = method_name end end end template end end
def template_name(opts)
def template_name(opts) opts[:template].to_s end
def template_path(opts)
def template_path(opts) path = "#{opts[:views]}/#{template_name(opts)}.#{opts[:engine]}" if opts.fetch(:check_paths){render_opts[:check_paths]} full_path = self.class.expand_path(path) unless render_opts[:allowed_paths].any?{|f| full_path.start_with?(f)} raise RodaError, "attempt to render path not in allowed_paths: #{full_path} (allowed: #{render_opts[:allowed_paths].join(', ')})" end end path end
def view(template, opts = (content = _optimized_view_content(template) unless defined?(yield); OPTS), &block)
are passed to render when rendering the template.
and render it inside the layout. Blocks passed to view
for the class, take the result of the template rendering
Render the given template. If there is a default layout
def view(template, opts = (content = _optimized_view_content(template) unless defined?(yield); OPTS), &block) if content # First, check if the optimized layout method has already been created, # and use it if so. This way avoids the extra conditional and local variable # assignments in the next section. if layout_method = _layout_method return send(layout_method, OPTS){content} end # If we have an optimized template method but no optimized layout method, create the # optimized layout method if possible and use it. If you can't create the optimized # layout method, fall through to the slower approach. if layout_template = self.class.opts[:render][:optimize_layout] retrieve_template(:template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout) if layout_method = _layout_method return send(layout_method, OPTS){content} end end else opts = parse_template_opts(template, opts) content = opts[:content] || render_template(opts, &block) end if layout_opts = view_layout_opts(opts) content = render_template(layout_opts){content} end content end
def view_layout_opts(opts)
rendering the layout template. If a layout should not be
If a layout should be used, return a hash of options for
def view_layout_opts(opts) if layout = opts.fetch(:layout, render_opts[:layout]) layout_opts = render_layout_opts method_layout_opts = opts[:layout_opts] layout_opts.merge!(method_layout_opts) if method_layout_opts case layout when Hash layout_opts.merge!(layout) when true # use default layout else layout_opts[:template] = layout end layout_opts end end