module Roda::RodaPlugins::Base::ClassMethods

def build_rack_app

Build the rack app to use
def build_rack_app
  if block = @route_block
    builder = Rack::Builder.new
    @middleware.each{|a, b| builder.use(*a, &b)}
    builder.run lambda{|env| allocate.call(env, &block)}
    @app = builder.to_app
  end
end

def call(env)

access to the underlying rack app.
However, for performance, it's better to use #app to get direct
This allows the class itself to be used as a rack application.
Call the internal rack application with the given environment.
def call(env)
  app.call(env)
end

def clear_middleware!

Clear the middleware stack
def clear_middleware!
  @middleware.clear
  build_rack_app
end

def freeze

it would cause some plugins to break.
Note that freezing the class prevents you from subclassing it, mostly because

be raised if you try to modify the internal state after calling this.
internal state at runtime anyway, but this makes sure an exception will
It's optional to call this method, as nothing should be modifying the
Freeze the internal state of the class, to avoid thread safety issues at runtime.
def freeze
  @opts.freeze
  @middleware.freeze
  super
end

def hash_matcher(key, &block)

def hash_matcher(key, &block)
  RodaPlugins.deprecate("Roda.hash_matcher is deprecated and will be removed in Roda 2.  It has been moved to the hash_matcher plugin.")
  self::RodaRequest.send(:define_method, :"match_#{key}", &block)
end

def inherited(subclass)

and setup the request and response subclasses.
When inheriting Roda, copy the shared data into the subclass,
def inherited(subclass)
  raise RodaError, "Cannot subclass a frozen Roda class" if frozen?
  super
  subclass.instance_variable_set(:@inherit_middleware, @inherit_middleware)
  subclass.instance_variable_set(:@middleware, @inherit_middleware ? @middleware.dup : [])
  subclass.instance_variable_set(:@opts, opts.dup)
  subclass.opts.to_a.each do |k,v|
    if (v.is_a?(Array) || v.is_a?(Hash)) && !v.frozen?
      subclass.opts[k] = v.dup
      if v.is_a?(RodaDeprecateMutation)
        subclass.opts[k].extend(RodaDeprecateMutation)
      end
    end
  end
  subclass.instance_variable_set(:@route_block, @route_block)
  subclass.send(:build_rack_app)
  
  request_class = Class.new(self::RodaRequest)
  request_class.roda_class = subclass
  request_class.match_pattern_cache = thread_safe_cache
  subclass.const_set(:RodaRequest, request_class)
  response_class = Class.new(self::RodaResponse)
  response_class.roda_class = subclass
  subclass.const_set(:RodaResponse, response_class)
end

def module_include(type, mod)

REMOVE20
def module_include(type, mod)
  if type == :response
    klass = self::RodaResponse
    iv = :@response_module
  else
    klass = self::RodaRequest
    iv = :@request_module
  end
  if mod
    raise RodaError, "can't provide both argument and block to response_module" if block_given?
    klass.send(:include, mod)
  else
    if instance_variable_defined?(iv)
      mod = instance_variable_get(iv)
    else
      mod = instance_variable_set(iv, Module.new)
      klass.send(:include, mod)
    end
    mod.module_eval(&Proc.new) if block_given?
  end
  mod
end

def plugin(plugin, *args, &block)

Roda.plugin :csrf
Roda.plugin PluginModule

which will be required and then used.
which is used directly, or a symbol represented a registered plugin
Load a new plugin into the current class. A plugin can be a module
def plugin(plugin, *args, &block)
  raise RodaError, "Cannot subclass a frozen Roda class" if frozen?
  plugin = RodaPlugins.load_plugin(plugin) if plugin.is_a?(Symbol)
  plugin.load_dependencies(self, *args, &block) if plugin.respond_to?(:load_dependencies)
  include(plugin::InstanceMethods) if defined?(plugin::InstanceMethods)
  extend(plugin::ClassMethods) if defined?(plugin::ClassMethods)
  self::RodaRequest.send(:include, plugin::RequestMethods) if defined?(plugin::RequestMethods)
  self::RodaRequest.extend(plugin::RequestClassMethods) if defined?(plugin::RequestClassMethods)
  self::RodaResponse.send(:include, plugin::ResponseMethods) if defined?(plugin::ResponseMethods)
  self::RodaResponse.extend(plugin::ResponseClassMethods) if defined?(plugin::ResponseClassMethods)
  plugin.configure(self, *args, &block) if plugin.respond_to?(:configure)
end

def request_module(mod = nil, &block)

def request_module(mod = nil, &block)
  RodaPlugins.deprecate("Roda.request_module is deprecated and will be removed in Roda 2.  It has been moved to the module_include plugin.")
  module_include(:request, mod, &block)
end

def response_module(mod = nil, &block)

def response_module(mod = nil, &block)
  RodaPlugins.deprecate("Roda.response_module is deprecated and will be removed in Roda 2.  It has been moved to the module_include plugin.")
  module_include(:response, mod, &block)
end

def route(&block)

times will overwrite the previous routing.
This should only be called once per class, and if called multiple

end
end
"Root"
r.root do
Roda.route do |r|

argument should be named +r+. Example:
a block, which is yielded the request. By convention, the block
underlying rack application using the stored middleware. Requires
Setup routing tree for the current Roda application, and build the
def route(&block)
  @route_block = block
  build_rack_app
end

def thread_safe_cache

easily overridden for alternative implementations.
A new thread safe cache instance. This is a method so it can be
def thread_safe_cache
  RodaCache.new
end

def use(*args, &block)

Roda.use Rack::Session::Cookie, :secret=>ENV['secret']

called before calling #route to have an effect. Example:
Add a middleware to use for the rack application. Must be
def use(*args, &block)
  @middleware << [args, block].freeze
  build_rack_app
end