lib/roda/plugins/render.rb in roda-3.39.0 vs lib/roda/plugins/render.rb in roda-3.40.0

- old
+ new

@@ -331,10 +331,29 @@ end end end module ClassMethods + # :nocov: + if COMPILED_METHOD_SUPPORT + # :nocov: + # If using compiled methods and there is an optimized layout, speed up + # access to the layout method to improve the performance of view. + def freeze + begin + _freeze_layout_method + rescue + # This is only for optimization, if any errors occur, they can be ignored. + # One possibility for error is the app doesn't use a layout, but doesn't + # specifically set the :layout=>false plugin option. + nil + end + + super + end + end + # Copy the rendering options into the subclass, duping # them as necessary to prevent changes in the subclass # affecting the parent class. def inherited(subclass) super @@ -350,10 +369,31 @@ # Return the render options for this class. def render_opts opts[:render] end + + private + + # Precompile the layout method, to reduce method calls to look it up at runtime. + def _freeze_layout_method + if render_opts[:layout] + instance = allocate + instance.send(:retrieve_template, instance.send(:view_layout_opts, OPTS)) + + # :nocov: + if COMPILED_METHOD_SUPPORT + # :nocov: + if (layout_template = render_opts[:optimize_layout]) && !opts[:render][:optimized_layout_method_created] + instance.send(:retrieve_template, :template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout) + layout_method = opts[:render][:template_method_cache][:_roda_layout] + define_method(:_layout_method){layout_method} + opts[:render] = opts[:render].merge(:optimized_layout_method_created=>true) + end + end + end + end end module InstanceMethods # Render the given template. See Render for details. def render(template, opts = (no_opts = true; optimized_template = _cached_template_method(template); OPTS), &block) @@ -377,19 +417,23 @@ # and render it inside the layout. See Render for details. def view(template, opts = (optimized_template = _cached_template_method(template); OPTS)) if optimized_template content = send(optimized_template, OPTS) - render_opts = self.class.opts[:render] - if layout_template = render_opts[:optimize_layout] - method_cache = render_opts[:template_method_cache] - unless layout_method = method_cache[:_roda_layout] - retrieve_template(:template=>layout_template, :cache_key=>nil, :template_method_cache_key => :_roda_layout) - layout_method = method_cache[:_roda_layout] - end + # 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 layout_method + # 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) @@ -426,10 +470,15 @@ # Return the instance method symbol for the template in the method cache. def _cached_template_method_lookup(method_cache, template) method_cache[template] end + # Return a symbol containing the optimized layout method + def _layout_method + self.class.opts[:render][:template_method_cache][:_roda_layout] + end + # Use an optimized render path for templates with a hash of locals. Returns the result # of the template render if the optimized path is used, or nil if the optimized # path is not used and the long method needs to be used. def _optimized_render_method_for_locals(template, locals) return unless method_cache = render_opts[:template_method_cache] @@ -469,14 +518,18 @@ end end end else # :nocov: - def _cached_template_method(template) + def _cached_template_method(_) nil end - def _cached_template_method_key(template) + def _cached_template_method_key(_) + nil + end + + def _layout_method nil end def _optimized_render_method_for_locals(_, _) nil