Module: Roda::RodaPlugins::ShapeFriendly

Defined in:
lib/roda/plugins/shape_friendly.rb

Overview

The shape_friendly plugin makes the scope, request, and response objects used by Roda friendly to object shapes, which can result in better performance on modern versions of Ruby, especially when the JIT compiler is enabled. All plugins shipped with Roda integrate with this plugin.

In order for this behavior to be beneficial for your application, you need to either avoid setting instance variables inside your routing tree, or you need to register each instance variable used, to ensure that all instances have the same shape.

If you want to avoid using instance variables in your routing tree, you can switch to using local variables. If using the render plugin, you can pass data from your routing tree to your views using the :locals option. When passing data from your routing tree to other routing trees, such as when using the hash_branches plugin, you can use the shared_vars plugin, which stores the data in the Rack environment.

To register instance variables set in your applications routing tree, use a :scope_instance_variables option when loading the plugin, listing the instance variable symbols you are setting in the route block scope:

class MyApp < Roda
plugin :shape_friendly, scope_instance_variables: [:@var1, @:var2]

route do |r|
  r.root do
    @var1 = "a"
    @var1.inspect
  end

  @var2 = "b"
  @var2.inspect
end
end

When developing external plugins, you can set one of three constants in the plugin module to integrate with this plugin to support shape friendly behavior:

  • SCOPE_INSTANCE_VARIABLES: For instance variables set in InstanceMethods.
  • REQUEST_INSTANCE_VARIABLES: For instance variables set in RequestMethods.
  • RESPONSE_INSTANCE_VARIABLES: For instance variables set in ResponseMethods.

These constants are set in the plugin module, not in the plugin's InstanceMethods, RequestMethods, or ResponseMethods modules, to avoid pollution of the related namespaces in the class loading the plugin.

Defined Under Namespace

Modules: ClassMethods, InstanceMethods, OptimizedInstanceMethods, OptimizedRequestMethods, OptimizedResponseMethods, UnoptimizedInstanceMethods, UnoptimizedRequestMethods, UnoptimizedResponseMethods

Constant Summary collapse

RESPONSE_INSTANCE_VARIABLES =

This is used by the base support and not by this plugin.

[:@status].freeze

Class Method Summary collapse

Class Method Details

.configure(app, opts = OPTS) ⇒ Object

Set the Roda application to create the private _initialize_nil_instance_variables for the plugin to use.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/roda/plugins/shape_friendly.rb', line 59

def self.configure(app, opts=OPTS)
  if scope_ivs = opts[:scope_instance_variables]
    app.opts[:shape_friendly_scope_instance_variables] = Array(scope_ivs).dup.freeze
  end

  app.instance_exec do
    def_initialize_nil_instance_variables(app, :SCOPE_INSTANCE_VARIABLES)
    def_initialize_nil_instance_variables(app::RodaRequest, :REQUEST_INSTANCE_VARIABLES)
    def_initialize_nil_instance_variables(app::RodaResponse, :RESPONSE_INSTANCE_VARIABLES)

    # Avoid overhead of super call if possible
    include(instance_method(:initialize).owner == Roda::RodaPlugins::Base::InstanceMethods ? OptimizedInstanceMethods : UnoptimizedInstanceMethods)
    app::RodaRequest.send(:include, app::RodaRequest.instance_method(:initialize).owner == Roda::RodaPlugins::Base::RequestMethods ? OptimizedRequestMethods : UnoptimizedRequestMethods)
    app::RodaResponse.send(:include, app::RodaResponse.instance_method(:initialize).owner == Roda::RodaPlugins::Base::ResponseMethods ? OptimizedResponseMethods : UnoptimizedResponseMethods)
  end
end