module Roda::RodaPlugins::Render

  1. lib/roda/plugins/render.rb
  2. lib/roda/plugins/render_each.rb
  3. lib/roda/plugins/render_locals.rb
  4. lib/roda/plugins/view_options.rb
  5. show all

The render plugin adds support for template rendering using the tilt library. Two methods are provided for template rendering, view (which uses the layout) and render (which does not).

plugin :render

route do |r|
  r.is 'foo' do
    view('foo') # renders views/foo.erb inside views/layout.erb
  end

  r.is 'bar' do
    render('bar') # renders views/bar.erb
  end
end

The render and view methods just return strings, they do not have side effects (unless the templates themselves have side effects). As Roda uses the routing block return value as the body of the response, in most cases you will call these methods as the last expression in a routing block to have the response body be the result of the template rendering.

Because render and view just return strings, you can call them inside templates (i.e. for subtemplates/partials), or multiple times in the same route and combine the results together:

route do |r|
  r.is 'foo-bars' do
    @bars = Bar.where(:foo).map{|b| render(:bar, locals: {bar: b})}.join
    view('foo')
  end
end

You can provide options to the plugin method:

plugin :render, engine: 'haml', views: 'admin_views'

Plugin Options

The following plugin options are supported:

:allowed_paths

Set the template paths to allow. Attempts to render paths outside of this directory will raise an error. Defaults to the :views directory.

:cache

nil/false to explicitly disable premanent template caching. By default, permanent template caching is disabled by default if RACK_ENV is development. When permanent template caching is disabled, for templates with paths in the file system, the modification time of the file will be checked on every render, and if it has changed, a new template will be created for the current content of the file.

:cache_class

A class to use as the template cache instead of the default.

:check_paths

Can be set to false to turn off template path checking.

:engine

The tilt engine to use for rendering, also the default file extension for templates, defaults to 'erb'.

:escape

Use Erubi as the ERB template engine, and enable escaping by default, which makes <%= %> escape output and <%== %> not escape output. If given, sets the :escape=>true option for all template engines, which can break some non-ERB template engines. You can use a string or array of strings as the value for this option to only set the :escape=>true option for those specific template engines.

:layout

The base name of the layout file, defaults to 'layout'. This can be provided as a hash with the :template or :inline options.

:layout_opts

The options to use when rendering the layout, if different from the default options.

:template_opts

The tilt options used when rendering all templates. defaults to: {outvar: '@_out_buf', default_encoding: Encoding.default_external}.

:engine_opts

The tilt options to use per template engine. Keys are engine strings, values are hashes of template options.

:views

The directory holding the view files, defaults to the 'views' subdirectory of the application's :root option (the process's working directory by default).

Render/View Method Options

Most of these options can be overridden at runtime by passing options to the view or render methods:

view('foo', engine: 'html.erb')
render('foo', views: 'admin_views')

There are additional options to view and render that are available at runtime:

:cache

Set to false to not cache this template, even when caching is on by default. Set to true to force caching for this template, even when the default is to not permantently cache (e.g. when using the :template_block option).

:cache_key

Explicitly set the hash key to use when caching.

:content

Only respected by view, provides the content to render inside the layout, instead of rendering a template to get the content.

:inline

Use the value given as the template code, instead of looking for template code in a file.

:locals

Hash of local variables to make available inside the template.

:path

Use the value given as the full pathname for the file, instead of using the :views and :engine option in combination with the template name.

:scope

The object in which context to evaluate the template. By default, this is the Roda instance.

:template

Provides the name of the template to use. This allows you pass a single options hash to the render/view method, while still allowing you to specify the template name.

:template_block

Pass this block when creating the underlying template, ignored when using :inline. Disables caching of the template by default.

:template_class

Provides the template class to use, instead of using Tilt or Tilt[:engine].

Here's an example of using these options:

view(inline: '<%= @foo %>')
render(path: '/path/to/template.erb')

If you pass a hash as the first argument to view or render, it should have either :template, :inline, :path, or :content (for view) as one of the keys.

Speeding Up Template Rendering

The render/view method calls are optimized for usage with a single symbol/string argument specifying the template name. So for fastest rendering, pass only a symbol/string to render/view. Next best optimized are template calls with a single :locals option. Use of other options disables the compiled template method optimizations and can be significantly slower.

If you must pass a hash to render/view, either as a second argument or as the only argument, you can speed things up by specifying a :cache_key option in the hash, making sure the :cache_key is unique to the template you are rendering.

Constants

COMPILED_METHOD_SUPPORT = RUBY_VERSION >= '2.3' && tilt_compiled_method_support  
NO_CACHE = {:cache=>false}.freeze  

Public Class methods

configure(app, opts=OPTS)

Setup default rendering options. See Render for details.

[show source]
    # File lib/roda/plugins/render.rb
154 def self.configure(app, opts=OPTS)
155   if app.opts[:render]
156     orig_cache = app.opts[:render][:cache]
157     orig_method_cache = app.opts[:render][:template_method_cache]
158     opts = app.opts[:render][:orig_opts].merge(opts)
159   end
160   app.opts[:render] = opts.dup
161   app.opts[:render][:orig_opts] = opts
162 
163   opts = app.opts[:render]
164   opts[:engine] = (opts[:engine] || "erb").dup.freeze
165   opts[:views] = app.expand_path(opts[:views]||"views").freeze
166   opts[:allowed_paths] ||= [opts[:views]].freeze
167   opts[:allowed_paths] = opts[:allowed_paths].map{|f| app.expand_path(f, nil)}.uniq.freeze
168   opts[:check_paths] = true unless opts.has_key?(:check_paths)
169 
170   unless opts.has_key?(:check_template_mtime)
171     opts[:check_template_mtime] = if opts[:cache] == false || opts[:explicit_cache]
172       true
173     else
174       ENV['RACK_ENV'] == 'development'
175     end
176   end
177 
178   begin
179     app.const_get(:RodaCompiledTemplates, false)
180   rescue NameError
181     compiled_templates_module = Module.new
182     app.send(:include, compiled_templates_module)
183     app.const_set(:RodaCompiledTemplates, compiled_templates_module)
184   end
185   opts[:template_method_cache] = orig_method_cache || (opts[:cache_class] || RodaCache).new
186   opts[:template_method_cache][:_roda_layout] = nil if opts[:template_method_cache][:_roda_layout]
187   opts[:cache] = orig_cache || (opts[:cache_class] || RodaCache).new
188 
189   opts[:layout_opts] = (opts[:layout_opts] || {}).dup
190   opts[:layout_opts][:_is_layout] = true
191   if opts[:layout_opts][:views]
192     opts[:layout_opts][:views] = app.expand_path(opts[:layout_opts][:views]).freeze
193   end
194 
195   if layout = opts.fetch(:layout, true)
196     opts[:layout] = true
197 
198     case layout
199     when Hash
200       opts[:layout_opts].merge!(layout)
201     when true
202       opts[:layout_opts][:template] ||= 'layout'
203     else
204       opts[:layout_opts][:template] = layout
205     end
206 
207     opts[:optimize_layout] = (opts[:layout_opts][:template] if opts[:layout_opts].keys.sort == [:_is_layout, :template])
208   end
209   opts[:layout_opts].freeze
210 
211   template_opts = opts[:template_opts] = (opts[:template_opts] || {}).dup
212   template_opts[:outvar] ||= '@_out_buf'
213   unless template_opts.has_key?(:default_encoding)
214     template_opts[:default_encoding] = Encoding.default_external
215   end
216 
217   engine_opts = opts[:engine_opts] = (opts[:engine_opts] || {}).dup
218   engine_opts.to_a.each do |k,v|
219     engine_opts[k] = v.dup.freeze
220   end
221 
222   if escape = opts[:escape]
223     require 'tilt/erubi'
224 
225     case escape
226     when String, Array
227       Array(escape).each do |engine|
228         engine_opts[engine] = (engine_opts[engine] || {}).merge(:escape => true).freeze
229       end
230     else
231       template_opts[:escape] = true
232     end
233   end
234 
235   template_opts.freeze
236   engine_opts.freeze
237   opts.freeze
238 end
tilt_template_compiled_method(template, locals_keys, scope_class)
[show source]
    # File lib/roda/plugins/render.rb
142 def self.tilt_template_compiled_method(template, locals_keys, scope_class)
143   template.send(:compiled_method, locals_keys, scope_class)
144 end