Class: Hg::Controller

Inherits:
Object
  • Object
show all
Includes:
AbstractController::Callbacks
Defined in:
lib/hg/controller.rb

Overview

An Hg controller defines a number of handler functions for actions. These are analogous to the concept of "controller actions" in Rails.

Handlers

Handler methods have access to the following objects:

  • request: The request passed along by the Router.
  • params: The parameters passed along for this action by the Router.
  • user: The user that sent the request.

Filters

You have access to all of the same filters you're used to from ActionController. They can either be accessed in their normal form, or with handler in place of action in the method name. If the filter chain should be halted, you must call the halt method.

class BotController < Hg::Controller before_handler :require_login

private

  def 
    unless user.logged_in?
      respond 'You must be logged in to access this.'
      respond_with OrderBot::Chunks::Login and halt
    end
  end

end

TODO: Should this object be Controllers::Base?

Direct Known Subclasses

Hg::Controllers::ChunksController

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(request: {}, router: nil, handler_name: nil) ⇒ Controller

Create a new instance of Controller.

Parameters:

  • request (Hash) (defaults to: {})

    a customizable set of options

  • router (Hash) (defaults to: nil)

    a customizable set of options

  • handler_name (Hash) (defaults to: nil)

    a customizable set of options

Options Hash (request:):

  • The (Hash)

    incoming request.

Options Hash (router:):

  • The (Hg::Router)

    router that handled the request.

Options Hash (handler_name:):

  • The (String)

    name of the handler to be executed.



42
43
44
45
46
47
48
49
50
# File 'lib/hg/controller.rb', line 42

def initialize(request: {}, router: nil, handler_name: nil)
  @request = request
  # TODO: Test that params or parameters works, here.
  @params = ActiveSupport::HashWithIndifferentAccess.new(request.parameters || request.params)
  @user = request.user
  @performed = false
  @router = router
  @handler_name = handler_name.to_s
end

Instance Attribute Details

#handler_nameObject Also known as: action_name

Necessary for compatibility with ActiveSupport::Callbacks only and except options



59
60
61
# File 'lib/hg/controller.rb', line 59

def handler_name
  @handler_name
end

#paramsObject Also known as: parameters

Returns the value of attribute params.



52
53
54
# File 'lib/hg/controller.rb', line 52

def params
  @params
end

#requestObject

Returns the value of attribute request.



54
55
56
# File 'lib/hg/controller.rb', line 54

def request
  @request
end

#userObject

Returns the value of attribute user.



55
56
57
# File 'lib/hg/controller.rb', line 55

def user
  @user
end

Instance Method Details

#flash(message) ⇒ Object



137
138
139
140
141
# File 'lib/hg/controller.rb', line 137

def flash(message)
  message = message.sample if message.respond_to?(:sample)
  respond(message)
  show_typing
end

#haltObject

Halt the execution of the filter chain.



95
96
97
98
# File 'lib/hg/controller.rb', line 95

def halt
  # TODO: This is a gross hack. You're supposed to throw(:abort).
  @performed = true
end

#loggerObject

Expose the Sidekiq logger to the controller.



198
199
200
# File 'lib/hg/controller.rb', line 198

def logger
  Sidekiq::Logging.logger
end

#merged_contextActiveSupport::HashWithIndifferentAccess

Generate a context based on merging the params into the user's current context.

Returns:

  • (ActiveSupport::HashWithIndifferentAccess)

    The merged context.



123
124
125
126
127
# File 'lib/hg/controller.rb', line 123

def merged_context
  ActiveSupport::HashWithIndifferentAccess
    .new((user.context_hash || {})
    .merge(params))
end

#performed?Boolean

Will be set to true by calling halt, thus halting the execution of the filter chain.

Returns:

  • (Boolean)

See Also:

  • AbstractController::Base#performed?
  • #halt


90
91
92
# File 'lib/hg/controller.rb', line 90

def performed?
  @performed
end

#process_action(method_name, *args) ⇒ Object

Call the action. Override this in a subclass to modify the behavior around processing an action. This, and not #process, is the intended way to override action dispatching.

Notice that the first argument is the handler method to be dispatched which is not necessarily the same as the action name.

Providing this method allows us to use AbstractController::Callbacks



70
71
72
73
74
75
76
# File 'lib/hg/controller.rb', line 70

def process_action(method_name, *args)
  # TODO: The run_callbacks shouldn't be here, but for some reason including
  # AbstractController::Callbacks isn't overriding this method.
  run_callbacks(:process_action) do
    send_action(method_name, *args)
  end
end

#redirect_to(payload = {}) ⇒ Object

TODO: High - document and test



187
188
189
190
191
192
193
194
195
# File 'lib/hg/controller.rb', line 187

def redirect_to(payload = {})
  request.action = payload[:action]
  request.intent = payload[:action] || payload[:intent]
  request.route  = payload[:route]
  # TODO: Seems like we need a method for fetching params value.
  request.parameters = payload[:parameters] || payload[:params]

  @router.handle(request)
end

#respond(*args) ⇒ Object Also known as: reply, ask, respond_with

Send a message back to the user. It's possible to either pass a string, which will be delivered as a text message, or a chunk and its context:

respond Chunks::ConfirmBookingSuccess, Time.now

respond 'Sounds good!' TODO: Document these params



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/hg/controller.rb', line 150

def respond(*args)
  # If we're attempting to send back a simple text message...
  if args.first.is_a?(String)
    # ...deliver the message.

    message_text = args.first

    # TODO: Add this as a method to Bot.
    response = Facebook::Messenger::Bot.deliver(
      {
        recipient: {
          id: user.facebook_psid
        },
        message: {
          text: message_text
        }
      }, access_token: ENV['FB_ACCESS_TOKEN']
    )

    # Send to Chatbase
    if ENV['CHATBASE_API_KEY']
      ChatbaseAPIClient.new.send_bot_message(message_text, response)
    end
  # If we're attempting to deliver a chunk...
  elsif args.first.is_a?(Class)
    # ....deliver the chunk
    chunk_class = args[0]
    chunk_context = args[1] || {}

    chunk_class.new(recipient: user.facebook_psid, context: chunk_context).deliver
  end
end

#show_typingObject

Show a typing indicator to the user.



130
131
132
133
134
135
# File 'lib/hg/controller.rb', line 130

def show_typing
  Facebook::Messenger::Bot.deliver({
    recipient: {id: user.facebook_psid},
    sender_action: 'typing_on'
  }, access_token: ENV['FB_ACCESS_TOKEN'])
end

#t(*args) ⇒ Object



202
203
204
# File 'lib/hg/controller.rb', line 202

def t(*args)
  I18n.t(*args)
end