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 inInstanceMethods. -
REQUEST_INSTANCE_VARIABLES: For instance variables set inRequestMethods. -
RESPONSE_INSTANCE_VARIABLES: For instance variables set inResponseMethods.
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.
Classes and Modules
- Roda::RodaPlugins::ShapeFriendly::ClassMethods
- Roda::RodaPlugins::ShapeFriendly::InstanceMethods
- Roda::RodaPlugins::ShapeFriendly::OptimizedInstanceMethods
- Roda::RodaPlugins::ShapeFriendly::OptimizedRequestMethods
- Roda::RodaPlugins::ShapeFriendly::OptimizedResponseMethods
- Roda::RodaPlugins::ShapeFriendly::UnoptimizedInstanceMethods
- Roda::RodaPlugins::ShapeFriendly::UnoptimizedRequestMethods
- Roda::RodaPlugins::ShapeFriendly::UnoptimizedResponseMethods
Constants
| RESPONSE_INSTANCE_VARIABLES | = | [:@status].freeze |
This is used by the base support and not by this plugin. |
Public Class methods
Set the Roda application to create the private _initialize_nil_instance_variables for the plugin to use.
# File lib/roda/plugins/shape_friendly.rb 59 def self.configure(app, opts=OPTS) 60 if scope_ivs = opts[:scope_instance_variables] 61 app.opts[:shape_friendly_scope_instance_variables] = Array(scope_ivs).dup.freeze 62 end 63 64 app.instance_exec do 65 def_initialize_nil_instance_variables(app, :SCOPE_INSTANCE_VARIABLES) 66 def_initialize_nil_instance_variables(app::RodaRequest, :REQUEST_INSTANCE_VARIABLES) 67 def_initialize_nil_instance_variables(app::RodaResponse, :RESPONSE_INSTANCE_VARIABLES) 68 69 # Avoid overhead of super call if possible 70 include(instance_method(:initialize).owner == Roda::RodaPlugins::Base::InstanceMethods ? OptimizedInstanceMethods : UnoptimizedInstanceMethods) 71 app::RodaRequest.send(:include, app::RodaRequest.instance_method(:initialize).owner == Roda::RodaPlugins::Base::RequestMethods ? OptimizedRequestMethods : UnoptimizedRequestMethods) 72 app::RodaResponse.send(:include, app::RodaResponse.instance_method(:initialize).owner == Roda::RodaPlugins::Base::ResponseMethods ? OptimizedResponseMethods : UnoptimizedResponseMethods) 73 end 74 end