Class: Hg::Router
- Inherits:
-
Object
- Object
- Hg::Router
- Defined in:
- lib/hg/router.rb
Overview
The router is responsible for routing an incoming action to the appropriate controller:
router.handle({ action: 'orderPizza', parameters: { size: 'large', toppings: ['pepperoni', 'sausage'] } })
The handle
method expects a request
object consisting of, at least,
action
and parameters
keys. Postbacks and raw messages sent through an NLU
should use the same set of action and parameter names, so that request
objects
will look the same either way by the time they reach the router.
Creating a router
Add a router to your bot by subclassing Hg::Router
:
class PizzaBotRouter < Hg::Router; end
Adding routes
You can add a route for an action with the action
method:
class PizzaBotRouter < Hg::Router action 'orderPizza', controller: PizzaOrdersController, with: :create end
Here, we're specifying that the orderPizza
action should map to the
PizzaOrdersController
's create
handler method.
Note that it's probably a good idea to store your action names as constants.
The route map
The routes map is a hash with action names as keys, pointing at nested hash values with the following structure:
{ controller: PizzaOrderController, handler: :create }
Routing
The router will map an inbound request
to the appropriate handler method.
request
objects take the following form:
request = { action: 'orderPizza', parameters: { size: 'large', toppings: ['pepperoni', 'sausage'] } }
Passing a request
to handle
directly off the bot's router class will
call the action's matching handler method on its controller class:
PizzaBotRouter.handle(request) # => PizzaOrderController.call(:create)
Defined Under Namespace
Classes: ActionNotRegisteredError
Constant Summary collapse
- INTERNAL_ROUTES =
The actions used internally by Hg.
{ Hg::InternalActions::DISPLAY_CHUNK => { controller: Hg::Controllers::ChunksController, handler: :display_chunk } }
Class Method Summary collapse
-
.action(action_name, controller:, with:) ⇒ Object
Add the action to the routes map.
- .controller(controller_class, &block) ⇒ Object
-
.default(controller, handler_method_name) ⇒ Object
Set up a handler for the default action.
-
.handle(request) ⇒ Object
Handle an inbound request by finding its matching handler method and executing it.
-
.handler(action_name, handler_method_name) ⇒ Object
Add a route for an action from within a
controller
block. -
.inherited(subclass) ⇒ Object
Create a new class instance variable
routes
on any subclasses. -
.routes ⇒ Hash
The routes map.
Class Method Details
.action(action_name, controller:, with:) ⇒ Object
Add the action to the routes map.
103 104 105 106 107 108 109 110 |
# File 'lib/hg/router.rb', line 103 def action(action_name, controller:, with:) handler_method_name = with @routes[action_name] = { controller: controller, handler: handler_method_name } end |
.controller(controller_class, &block) ⇒ Object
125 126 127 128 129 |
# File 'lib/hg/router.rb', line 125 def controller(controller_class, &block) Thread.current[:current_controller] = controller_class yield end |
.default(controller, handler_method_name) ⇒ Object
Set up a handler for the default action.
162 163 164 165 166 |
# File 'lib/hg/router.rb', line 162 def default(controller, handler_method_name) action Hg::InternalActions::DEFAULT, controller: controller, with: handler_method_name end |
.handle(request) ⇒ Object
Handle an inbound request by finding its matching handler method and executing it.
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
# File 'lib/hg/router.rb', line 135 def handle(request) # Don't use the router if a route has already been specified. unless route = request.route begin route = routes.fetch(request.action) request.route = route rescue KeyError raise ActionNotRegisteredError.new(request.action) end end handler_name = route[:handler] controller_for_request = route[:controller].new( request: request, router: self, handler_name: handler_name ) controller_for_request.process_action(handler_name) end |
.handler(action_name, handler_method_name) ⇒ Object
Add a route for an action from within a controller
block.
117 118 119 120 121 122 123 |
# File 'lib/hg/router.rb', line 117 def handler(action_name, handler_method_name) # TODO: BUG Thread.current isn't going to work in case of multiple routers # Needs to be a concurrent object, or dry-ruby_configurable action(action_name, controller: Thread.current[:current_controller], with: handler_method_name) end |
.inherited(subclass) ⇒ Object
Create a new class instance variable routes
on any subclasses.
82 83 84 85 86 87 88 89 |
# File 'lib/hg/router.rb', line 82 def inherited(subclass) # Default routes to new hash. subclass.instance_variable_set(:@routes, {}) # TODO: Need to figure this out. # Since the class itself is the router, make it immutable for thread-safety. # subclass.freeze end |
.routes ⇒ Hash
Returns The routes map.
92 93 94 |
# File 'lib/hg/router.rb', line 92 def routes @memoized_routes ||= INTERNAL_ROUTES.merge(@routes) end |