class SlackRubyBot::MVC::Controller::Base

Attributes

abstract[R]
abstract?[R]
client[R]
data[R]
match[R]
model[R]
view[R]

Public Class Methods

abstract!() click to toggle source

Define a controller as abstract. See internal_methods for more details.

# File lib/slack-ruby-bot/mvc/controller/base.rb, line 43
def abstract!
  @abstract = true
end
aliases() click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 21
def aliases
  get_or_set_ivar(:@aliases, Hash.new { |h, k| h[k] = [] })
end
alternate_name(original_name, *alias_names) click to toggle source

Maps a controller method name to an alternate command name. Used in cases where a command can be called via multiple text strings.

Call this method after defining the original method.

Class.new(SlackRubyBot::MVC::Controller::Base) do
  def quxo_foo_bar
    client.say(channel: data.channel, text: "quxo foo bar: #{match[:expression]}")
  end
  # setup alias name after original method definition
  alternate_name :quxo_foo_bar, :another_text_string
end

This is equivalent to:

e.g.

command 'quxo foo bar', 'another text string' do |*args|
  ..
end
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 113
def alternate_name(original_name, *alias_names)
  command_name = convert_method_name_to_command_string(original_name)
  command_aliases = alias_names.map do |name|
    convert_method_name_to_command_string(name)
  end

  aliases[command_name] += command_aliases

  alias_names.each { |alias_name| alias_method(alias_name, original_name) }
end
command_class() click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 17
def command_class
  get_or_set_ivar(:@command_class, Class.new(SlackRubyBot::Commands::Base))
end
controllers() click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 13
def controllers
  get_or_set_ivar(:@controllers, [])
end
get_or_set_ivar(name, value) click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 25
def get_or_set_ivar(name, value)
  unless (ivar = Base.instance_variable_get(name))
    ivar = value
    Base.instance_variable_set(name, ivar)
  end
  ivar
end
internal_methods(controller) click to toggle source

A list of all internal methods for a controller. This finds the first abstract superclass of a controller, and gets a list of all public instance methods on that abstract class. Public instance methods of a controller would normally be considered action methods, so methods declared on abstract classes are being removed. (Controller::Base is defined as abstract)

# File lib/slack-ruby-bot/mvc/controller/base.rb, line 89
def internal_methods(controller)
  controller = controller.superclass until controller.abstract?
  controller.public_instance_methods(true)
end
new(model, view) click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 141
def initialize(model, view)
  @model = model
  @view = view
  self.class.register_controller(self)
end
register_controller(controller) click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 54
def register_controller(controller)
  # Only used to keep a reference around so the instance object doesn't get garbage collected
  controllers << controller
  klass = controller.class

  methods = (klass.public_instance_methods(true) -
             # Except for public instance methods of Base and its ancestors
             internal_methods(klass) +
             # Be sure to include shadowed public instance methods of this class
             klass.public_instance_methods(false)).uniq.map(&:to_s)

  methods.each do |name|
    next if name[0] == '_'

    commands = lookup_command_name(name)

    # Generates a command for each controller method *and* its aliases
    commands.each do |command_string|
      # sprinkle a little syntactic sugar on top of existing `command` infrastructure
      command_class.class_eval do
        command command_string do |client, data, match|
          controller.use_args(client, data, match)
          controller.call_command
        end
      end
    end
  end
end
reset!() click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 33
def reset!
  # Remove any earlier anonymous classes from prior calls so we don't leak them
  Commands::Base.command_classes.delete(Controller::Base.command_class) if Base.command_class

  Base.instance_variable_set(:@command_class, nil)
  Base.instance_variable_set(:@controllers, nil)
end

Private Class Methods

convert_method_name_to_command_string(name) click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 131
def convert_method_name_to_command_string(name)
  name.to_s.tr('_', ' ')
end
lookup_command_name(name) click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 126
def lookup_command_name(name)
  name = convert_method_name_to_command_string(name)
  [name] + aliases[name]
end

Public Instance Methods

call_command() click to toggle source

Determine the command issued and call the corresponding instance method

# File lib/slack-ruby-bot/mvc/controller/base.rb, line 158
def call_command
  verb = match.captures[match.names.index('command')]
  verb = normalize_command_string(verb)
  public_send(verb)
end
use_args(client, data, match) click to toggle source

Hand off the latest updated objects to the model and view and update our client, data, and match accessors.

# File lib/slack-ruby-bot/mvc/controller/base.rb, line 149
def use_args(client, data, match)
  @client = client
  @data = data
  @match = match
  model.use_args(client, data, match)
  view.use_args(client, data, match)
end

Private Instance Methods

normalize_command_string(string) click to toggle source
# File lib/slack-ruby-bot/mvc/controller/base.rb, line 166
def normalize_command_string(string)
  string.downcase.tr(' ', '_')
end