Module: ClassX::Pluggable

Extended by:
Attributes, Role::Logger
Included in:
MockContext
Defined in:
lib/classx/pluggable.rb,
lib/classx/pluggable/plugin.rb

Overview

in your context class.

require 'classx'
require 'classx/pluggable'
class YourApp
  include ClassX
  include ClassX::Pluggable

  def run
    call_event("SETUP", {})
    # you app
    call_event("TEARDOWN", {})
  end

end

in your plugin class

require 'classx'
require 'classx/pluggable'
class YourApp
  class Plugin
    include ClassX
    include ClassX::Pluggable::Plugin

    class SomePlugin < Plugin
      def register
        add_event("SETUP", :on_setup)
      end

      def on_setup param
        # param is Hash
        # hooked setup
      end
    end
  end
end

Defined Under Namespace

Modules: ClassMethods, Plugin, Util Classes: MockContext, PluginLoadError

Instance Method Summary collapse

Instance Method Details

#add_event(name, plugin, meth) ⇒ Object

register plugin and method to hook point.



72
73
74
75
76
77
78
79
80
# File 'lib/classx/pluggable.rb', line 72

def add_event name, plugin, meth
  name = name.to_s
  if self.check_events && !self.events.include?(name)
    raise "#{name.inspect} should be declared before call add_event. not in #{self.events.inspect}"
  else
    self.__classx_pluggable_events_of[name] ||= []
  end
  self.__classx_pluggable_events_of[name] << { :plugin => plugin, :method => meth }
end

#call_event(name, *args) ⇒ Object

invoke registered event of name with args. and return array of result each callback.



117
118
119
120
121
122
123
124
125
126
# File 'lib/classx/pluggable.rb', line 117

def call_event name, *args
  name = name.to_s
  if events = self.__classx_pluggable_events_of[name]
    events.map do |event|
      event[:plugin].__send__(event[:method], *args)
    end
  else
    []
  end
end

#call_event_around(name, *args, &block) ⇒ Object

invoke registered event of BEFORE_xxxx and yield block and invoke hook AFTER_xxxx.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/classx/pluggable.rb', line 129

def call_event_around name, *args, &block
  name = name.to_s
  around_name = "AROUND_#{name}"

  call_event("BEFORE_#{name}", *args)
  if events = self.__classx_pluggable_events_of[around_name]
    procs = []
    procs << block
    index = 0
    nested_proc = events.inject(block) {|bl, event| proc { event[:plugin].__send__(event[:method], *args, &bl ) } }
    nested_proc.call
  end
  call_event("AFTER_#{name}", *args)
end

#load_component(type, hash) ⇒ Object



106
107
108
109
110
111
112
113
114
# File 'lib/classx/pluggable.rb', line 106

def load_component type, hash
  component = OpenStruct.new(hash.dup)
  mod = self.class.component_class_get(type, component.module, { :plugin_dir => self.plugin_dir })
  component.config ||= {}
  component.config[:context] = self
  instance = mod.new(component.config)
  instance.register
  logger.debug("ClassX::Pluggable: loaded #{type} #{component.module}, config=#{instance.inspect}")
end

#load_components(type, components) ⇒ Object

if you customize Plugin name space. you can use this instead of load_plugins.

app.load_components('engine', [
   { :module => "YourApp::Engine::Foo", :confiig => { :some_config => "foo"} },
   { :module => "+Bar", :confiig => { } }, # It's same meaning of YourApp::Engine::Bar
])


100
101
102
103
104
# File 'lib/classx/pluggable.rb', line 100

def load_components type, components
  components.each do |component|
    load_component type, component
  end
end

#load_plugins(plugins) ⇒ Object

load plugins.

app.load_plugins([
  { :module => "YourApp::Plugin::Foo", :confiig => { :some_config => "foo"} },
  { :module => "+Bar", :confiig => { } }, # It's same meaning of YourApp::Plugin::Bar
])


89
90
91
# File 'lib/classx/pluggable.rb', line 89

def load_plugins plugins
  load_components("plugin", plugins)
end