Class: SlackRubyBot::MVC::Controller::Base

Inherits:
Object
  • Object
show all
Includes:
ActiveSupport::Callbacks
Defined in:
lib/slack-ruby-bot/mvc/controller/base.rb

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, view) ⇒ Base

Returns a new instance of Base.


140
141
142
143
144
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 140

def initialize(model, view)
  @model = model
  @view = view
  self.class.register_controller(self)
end

Class Attribute Details

.abstractObject (readonly) Also known as: abstract?

Returns the value of attribute abstract


8
9
10
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 8

def abstract
  @abstract
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client


138
139
140
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 138

def client
  @client
end

#dataObject (readonly)

Returns the value of attribute data


138
139
140
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 138

def data
  @data
end

#matchObject (readonly)

Returns the value of attribute match


138
139
140
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 138

def match
  @match
end

#modelObject (readonly)

Returns the value of attribute model


138
139
140
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 138

def model
  @model
end

#viewObject (readonly)

Returns the value of attribute view


138
139
140
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 138

def view
  @view
end

Class Method Details

.abstract!Object

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


41
42
43
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 41

def abstract!
  @abstract = true
end

.aliasesObject


19
20
21
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 19

def aliases
  get_or_set_ivar(:@aliases, Hash.new { |h, k| h[k] = [] })
end

.alternate_name(original_name, *alias_names) ⇒ Object

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

112
113
114
115
116
117
118
119
120
121
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 112

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_classObject


15
16
17
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 15

def command_class
  get_or_set_ivar(:@command_class, Class.new(SlackRubyBot::Commands::Base))
end

.controllersObject


11
12
13
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 11

def controllers
  get_or_set_ivar(:@controllers, [])
end

.get_or_set_ivar(name, value) ⇒ Object


23
24
25
26
27
28
29
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 23

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

.inherited(klass) ⇒ Object

:nodoc:


45
46
47
48
49
50
51
52
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 45

def inherited(klass) # :nodoc:
  # Define the abstract ivar on subclasses so that we don't get
  # uninitialized ivar warnings
  unless klass.instance_variable_defined?(:@abstract)
    klass.instance_variable_set(:@abstract, false)
  end
  super
end

.internal_methods(controller) ⇒ Object

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)


88
89
90
91
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 88

def internal_methods(controller)
  controller = controller.superclass until controller.abstract?
  controller.public_instance_methods(true)
end

.register_controller(controller) ⇒ Object


54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 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!Object


31
32
33
34
35
36
37
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 31

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

Instance Method Details

#call_commandObject

Determine the command issued and call the corresponding instance method


157
158
159
160
161
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 157

def call_command
  verb = match.captures[match.names.index('command')]
  verb = normalize_command_string(verb)
  public_send(verb)
end

#use_args(client, data, match) ⇒ Object

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


148
149
150
151
152
153
154
# File 'lib/slack-ruby-bot/mvc/controller/base.rb', line 148

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