From a97a1fc7452088b875edb6b258c92d6eab1c19a4 Mon Sep 17 00:00:00 2001 From: Cristian Bica Date: Thu, 23 Jul 2015 00:10:22 +0300 Subject: Improve channel actions dispatcher to allow inheritance/mixins Fixes #14 --- lib/action_cable/channel/base.rb | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'lib/action_cable') diff --git a/lib/action_cable/channel/base.rb b/lib/action_cable/channel/base.rb index 87ae3a1211..d6bd98d180 100644 --- a/lib/action_cable/channel/base.rb +++ b/lib/action_cable/channel/base.rb @@ -75,6 +75,42 @@ module ActionCable attr_reader :params, :connection delegate :logger, to: :connection + class << self + # A list of method names that should be considered actions. This + # includes all public instance methods on a channel, less + # any internal methods (defined on Base), adding back in + # any methods that are internal, but still exist on the class + # itself. + # + # ==== Returns + # * Set - A set of all methods that should be considered actions. + def action_methods + @action_methods ||= begin + # All public instance methods of this class, including ancestors + methods = (public_instance_methods(true) - + # Except for public instance methods of Base and its ancestors + ActionCable::Channel::Base.public_instance_methods(true) + + # Be sure to include shadowed public instance methods of this class + public_instance_methods(false)).uniq.map(&:to_s) + methods.to_set + end + end + + protected + # action_methods are cached and there is sometimes need to refresh + # them. ::clear_action_methods! allows you to do that, so next time + # you run action_methods, they will be recalculated + def clear_action_methods! + @action_methods = nil + end + + # Refresh the cached action_methods when a new action_method is added. + def method_added(name) + super + clear_action_methods! + end + end + def initialize(connection, identifier, params = {}) @connection = connection @identifier = identifier @@ -147,7 +183,7 @@ module ActionCable end def processable_action?(action) - self.class.instance_methods(false).include?(action) + self.class.action_methods.include?(action.to_s) end def dispatch_action(action, data) @@ -168,7 +204,6 @@ module ActionCable end end - def run_subscribe_callbacks self.class.on_subscribe_callbacks.each { |callback| send(callback) } end -- cgit v1.2.3