class Flame::Dispatcher

Helpers for dispatch Flame::Application#call

Constants

GEM_STATIC_FILES

Attributes

request[R]
response[R]

Public Class Methods

new(app, env) click to toggle source

Initialize Dispatcher from Application#call @param app [Flame::Application] application object @param env Rack-environment object

# File lib/flame/dispatcher.rb, line 25
def initialize(app, env)
        @app = app
        @env = env
        @request = Flame::Dispatcher::Request.new(env)
        @response = Flame::Dispatcher::Response.new
end

Public Instance Methods

body(value = nil) click to toggle source

Acccess to the body of response @param value [String, nil] string value for new body @return [String] current body @example Set body value

body 'Hello World!'
# File lib/flame/dispatcher.rb, line 60
def body(value = nil)
        value ? @body = value : @body ||= ''
end
cached_tilts() click to toggle source

All cached tilts (views) for application by Flame::Render

# File lib/flame/dispatcher.rb, line 146
def cached_tilts
        @app.class.cached_tilts
end
config() click to toggle source

Application-config object as Hash

# File lib/flame/dispatcher.rb, line 82
def config
        @app.config
end
cookies() click to toggle source

Cookies object as Hash

# File lib/flame/dispatcher.rb, line 77
def cookies
        @cookies ||= Cookies.new(request.cookies, response)
end
default_body() click to toggle source

Generate default body of error page

# File lib/flame/dispatcher.rb, line 140
def default_body
        # response.headers[Rack::CONTENT_TYPE] = 'text/html'
        "<h1>#{Rack::Utils::HTTP_STATUS_CODES[status]}</h1>"
end
dump_error(error) click to toggle source

Add error's backtrace to @env (terminal or file) @param error [Exception] exception for class, message and backtrace

# File lib/flame/dispatcher.rb, line 130
def dump_error(error)
        error_message = [
                "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')} - " \
                "#{error.class} - #{error.message}:",
                *error.backtrace
        ].join("\n\t")
        @env[Rack::RACK_ERRORS].puts(error_message)
end
halt(new_status = nil, new_body = nil, new_headers = {}) click to toggle source

Interrupt the execution of route, and set new optional data

(otherwise using existing)

@param new_status [Integer, nil]

set new HTTP status code

@param new_body [String, nil] set new body @param new_headers [Hash, nil] merge new headers @example Halt, no change status or body

halt

@example Halt with 500, no change body

halt 500

@example Halt with 404, render template

halt 404, render('errors/404')

@example Halt with 200, set new headers

halt 200, 'Cats!', 'Content-Type' => 'animal/cat'
# File lib/flame/dispatcher.rb, line 121
def halt(new_status = nil, new_body = nil, new_headers = {})
        status new_status if new_status
        body new_body || (default_body_of_nearest_route if body.empty?)
        response.headers.merge!(new_headers)
        throw :halt
end
params() click to toggle source

Parameters of the request

# File lib/flame/dispatcher.rb, line 67
def params
        @params ||= request.params.symbolize_keys(deep: true)
end
path_to(ctrl, action = :index, args = {}) click to toggle source

Build a path to the given controller and action, with any expected params

@param ctrl [Flame::Controller] class of controller @param action [Symbol] method of controller @param args [Hash] parameters for method of controller @return [String] path for requested method, controller and parameters @example Path for `show(id)` method of `ArticlesController` with `id: 2`

path_to ArticlesController, :show, id: 2 # => "/articles/show/2"

@example Path for `new` method of `ArticlesController` with params

path_to ArticlesController, :new, params: { author_id: 1 }
# => "/articles/new?author_id=1"
# File lib/flame/dispatcher.rb, line 97
def path_to(ctrl, action = :index, args = {})
        route = @app.class.router.find_route(controller: ctrl, action: action)
        raise Errors::RouteNotFoundError.new(ctrl, action) unless route
        query = Rack::Utils.build_nested_query args.delete(:params)
        query = nil if query&.empty?
        path = route.path.assign_arguments(args)
        path = '/' if path.empty?
        URI::Generic.build(path: path, query: query).to_s
end
run!() click to toggle source

Start of execution the request

# File lib/flame/dispatcher.rb, line 33
def run!
        catch :halt do
                try_static ||
                        try_static(dir: GEM_STATIC_FILES) ||
                        try_route ||
                        halt(404)
        end
        response.write body unless request.http_method == :HEAD
        response.finish
end
session() click to toggle source

Session object as Hash

# File lib/flame/dispatcher.rb, line 72
def session
        request.session
end
status(value = nil) click to toggle source

Acccess to the status of response @param value [Ineger, nil] integer value for new status @return [Integer] current status @example Set status value

status 200
# File lib/flame/dispatcher.rb, line 49
def status(value = nil)
        response.status ||= 200
        response.headers['X-Cascade'] = 'pass' if value == 404
        value ? response.status = value : response.status
end

Private Instance Methods

default_body_of_nearest_route() click to toggle source

Generate a default body of nearest route

# File lib/flame/dispatcher.rb, line 180
def default_body_of_nearest_route
        ## Return nil if must be no body for current HTTP status
        return if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status)
        ## Find the nearest route by the parts of requested path
        route = @app.router.find_nearest_route(request.path)
        ## Return nil if the route not found
        ##   or it's `default_body` method not defined
        return default_body unless route
        ## Execute `default_body` method for the founded route
        execute_route(route, :default_body)
        default_body if body.empty?
end
execute_route(route, action = route.action) click to toggle source

Execute route @param route [Flame::Route] route that must be executed

# File lib/flame/dispatcher.rb, line 165
def execute_route(route, action = route.action)
        params.merge! route.path.extract_arguments(request.path)
        # route.execute(self)
        controller = route.controller.new(self)
        controller.send(:execute, action)
rescue => exception
        # p 'rescue from dispatcher'
        dump_error(exception)
        status 500
        controller&.send(:server_error, exception)
        # p 're raise exception from dispatcher'
        # raise exception
end
try_route() click to toggle source

Find route and try execute it

# File lib/flame/dispatcher.rb, line 153
def try_route
        route = @app.class.router.find_route(
                method: request.http_method,
                path: request.path
        )
        return nil unless route
        status 200
        execute_route(route)
end