class Flame::Dispatcher
Helpers for dispatch Flame::Application#call
Constants
- GEM_STATIC_FILES
Attributes
Public Class Methods
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
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
All cached tilts (views) for application by Flame::Render
# File lib/flame/dispatcher.rb, line 146 def cached_tilts @app.class.cached_tilts end
Application-config object as Hash
# File lib/flame/dispatcher.rb, line 82 def config @app.config end
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
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
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
Parameters of the request
# File lib/flame/dispatcher.rb, line 67 def params @params ||= request.params.symbolize_keys(deep: true) end
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
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 object as Hash
# File lib/flame/dispatcher.rb, line 72 def session request.session end
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
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 @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
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