lib/roda/plugins/render.rb in roda-2.16.0 vs lib/roda/plugins/render.rb in roda-2.17.0

- old
+ new

@@ -18,10 +18,28 @@ # 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 @@ -44,13 +62,16 @@ # :escape_safe_classes :: String subclasses that should not be HTML escaped when used in # <tt><%= %></tt> tags, when :escape is used. Can be an array for multiple classes. # :escaper :: Object used for escaping output of <tt><%= %></tt>, when :escape is used, # overriding the default. If given, object should respond to +escape_xml+ with # a single argument and return an output string. - # :layout :: The base name of the layout file, defaults to 'layout'. + # :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. + # from the default options. To pass local variables to the layout, include a :locals + # option inside :layout_opts. To automatically merge the view template locals into + # the layout template locals, include a :merge_locals option inside :layout_opts. # :template_opts :: The tilt options used when rendering all templates. defaults to: # <tt>{:outvar=>'@_out_buf', :default_encoding=>Encoding.default_external}</tt>. # :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 @@ -152,10 +173,15 @@ end end opts[:layout_opts] = (opts[:layout_opts] || {}).dup opts[:layout_opts][:_is_layout] = true + + if opts[:layout_opts][:merge_locals] && opts[:locals] + opts[:layout_opts][:locals] = opts[:locals].merge(opts[:layout_opts][:locals] || {}) + end + if layout = opts.fetch(:layout, true) opts[:layout] = true unless opts.has_key?(:layout) case layout when Hash @@ -371,19 +397,34 @@ # If a layout should be used, return a hash of options for # rendering the layout template. If a layout should not be # used, return nil. def view_layout_opts(opts) if layout = opts.fetch(:layout, render_opts[:layout]) + layout_opts = render_layout_opts - if l_opts = opts[:layout_opts] - if (l_locals = l_opts[:locals]) && (layout_locals = layout_opts[:locals]) - set_locals = Hash[layout_locals].merge!(l_locals) - end - layout_opts.merge!(l_opts) - if set_locals - layout_opts[:locals] = set_locals - end + merge_locals = layout_opts[:merge_locals] + + if method_layout_opts = opts[:layout_opts] + method_layout_locals = method_layout_opts[:locals] + merge_locals = method_layout_opts[:merge_locals] if method_layout_opts.has_key?(:merge_locals) end + + locals = {} + if merge_locals && (plugin_locals = render_opts[:locals]) + locals.merge!(plugin_locals) + end + if layout_locals = layout_opts[:locals] + locals.merge!(layout_locals) + end + if merge_locals && (method_locals = opts[:locals]) + locals.merge!(method_locals) + end + if method_layout_locals + locals.merge!(method_layout_locals) + end + + layout_opts.merge!(method_layout_opts) if method_layout_opts + layout_opts[:locals] = locals unless locals.empty? case layout when Hash layout_opts.merge!(layout) when true