module Roda::RodaPlugins::Base::ClassMethods

Class methods for the Roda class.

Attributes

app[R]

The rack application that this class uses.

opts[R]

The settings/options hash for the current class.

route_block[R]

The route block that this class uses.

Public Instance Methods

call(env) click to toggle source

Call the internal rack application with the given environment. This allows the class itself to be used as a rack application. However, for performance, it’s better to use app to get direct access to the underlying rack app.

# File lib/roda.rb, line 105
def call(env)
  app.call(env)
end
hash_matcher(key, &block) click to toggle source

Create a match_#{key} method in the request class using the given block, so that using a hash key in a request match method will call the block. The block should return nil or false to not match, and anything else to match.

class App < Roda
  hash_matcher(:foo) do |v|
    self['foo'] == v
  end

  route do
    r.on :foo=>'bar' do
      # matches when param foo has value bar
    end
  end
end
# File lib/roda.rb, line 125
def hash_matcher(key, &block)
  request_module{define_method(:"match_#{key}", &block)}
end
inherited(subclass) click to toggle source

When inheriting Roda, copy the shared data into the subclass, and setup the request and response subclasses.

Calls superclass method
# File lib/roda.rb, line 131
def inherited(subclass)
  super
  subclass.instance_variable_set(:@middleware, @middleware.dup)
  subclass.instance_variable_set(:@opts, opts.dup)
  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
plugin(mixin, *args, &block) click to toggle source

Load a new plugin into the current class. A plugin can be a module which is used directly, or a symbol represented a registered plugin which will be required and then used.

Roda.plugin PluginModule
Roda.plugin :csrf
# File lib/roda.rb, line 154
def plugin(mixin, *args, &block)
  if mixin.is_a?(Symbol)
    mixin = RodaPlugins.load_plugin(mixin)
  end

  if mixin.respond_to?(:load_dependencies)
    mixin.load_dependencies(self, *args, &block)
  end

  if defined?(mixin::InstanceMethods)
    include mixin::InstanceMethods
  end
  if defined?(mixin::ClassMethods)
    extend mixin::ClassMethods
  end
  if defined?(mixin::RequestMethods)
    self::RodaRequest.send(:include, mixin::RequestMethods)
  end
  if defined?(mixin::RequestClassMethods)
    self::RodaRequest.extend mixin::RequestClassMethods
  end
  if defined?(mixin::ResponseMethods)
    self::RodaResponse.send(:include, mixin::ResponseMethods)
  end
  if defined?(mixin::ResponseClassMethods)
    self::RodaResponse.extend mixin::ResponseClassMethods
  end
  
  if mixin.respond_to?(:configure)
    mixin.configure(self, *args, &block)
  end
end
request_module(mod = nil, &block) click to toggle source

Include the given module in the request class. If a block is provided instead of a module, create a module using the the block. Example:

Roda.request_module SomeModule

Roda.request_module do
  def description
    "#{request_method} #{path_info}"
  end
end

Roda.route do |r|
  r.description
end
# File lib/roda.rb, line 202
def request_module(mod = nil, &block)
  module_include(:request, mod, &block)
end
response_module(mod = nil, &block) click to toggle source

Include the given module in the response class. If a block is provided instead of a module, create a module using the the block. Example:

Roda.response_module SomeModule

Roda.response_module do
  def error!
    self.status = 500
  end
end

Roda.route do |r|
  response.error!
end
# File lib/roda.rb, line 221
def response_module(mod = nil, &block)
  module_include(:response, mod, &block)
end
route(&block) click to toggle source

Setup routing tree for the current Roda application, and build the underlying rack application using the stored middleware. Requires a block, which is yielded the request. By convention, the block argument should be named r. Example:

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

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

# File lib/roda.rb, line 238
def route(&block)
  @route_block = block
  build_rack_app
end
thread_safe_cache() click to toggle source

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

# File lib/roda.rb, line 245
def thread_safe_cache
  RodaCache.new
end
use(*args, &block) click to toggle source

Add a middleware to use for the rack application. Must be called before calling route to have an effect. Example:

Roda.use Rack::Session::Cookie, :secret=>ENV['secret']
# File lib/roda.rb, line 253
def use(*args, &block)
  @middleware << [args, block]
  build_rack_app
end

Private Instance Methods

build_rack_app() click to toggle source

Build the rack app to use

# File lib/roda.rb, line 261
def build_rack_app
  if block = @route_block
    builder = Rack::Builder.new
    @middleware.each{|a, b| builder.use(*a, &b)}
    builder.run lambda{|env| new.call(env, &block)}
    @app = builder.to_app
  end
end
module_include(type, mod) click to toggle source

Backbone of the request_module and response_module support.

# File lib/roda.rb, line 271
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
    unless mod = instance_variable_get(iv)
      mod = instance_variable_set(iv, Module.new)
      klass.send(:include, mod)
    end

    mod.module_eval(&Proc.new) if block_given?
  end

  mod
end