Reputation: 66851
I'm trying to create a component system in Ruby using the observer pattern. Components must be defined as modules because they exist only to be mixed in to a ComponentContainer
. But there are certain methods that Component
s have, which I'd ideally like to define in some kind of base class, but I can't do that since they're modules.
Here's what I'd like to do:
module Component
def self.on(event, &block)
#definition..
end
def self.fire(event)
#pass event to subscribers
end
end
module FooComponent < Component
on :foo_event do |param1, param2|
#...
end
end
The different types of Component
s use the on
and fire
methods, but they can't inherit them, because modules can't have parents. What should I do? Is this not ruby-like?
I could get this to work by making Component
and FooComponent
classes, but then I can't mix them into a ComponentContainer
using extend
or include
.
Upvotes: 2
Views: 153
Reputation: 1854
A clean way to do this is to abstract away the use of extend
using the Module#included
hook method. This method is called on a module with a reference to the base that is including it. What this code does is creates a Component
module that automatically extends the base with the desired methods:
module Component
def self.included(base)
base.extend Methods
end
module Methods
def on(event, &block)
# ...
end
def fire(event)
# ...
end
end
end
module FooComponent
include Component
on :foo_event do |param1, param2|
# ...
end
end
Upvotes: 3
Reputation: 9177
You can extend the Component
's methods into your "child"-module:
module Component
extend self # (only if you also want to allow calling via Component.on like in the original example)
def on(event, &block)
#definition..
end
def fire(event)
#pass event to subscribers
end
end
module FooComponent
extend Component
on :foo_event do |param1, param2|
#...
end
end
Upvotes: 2
Reputation: 5593
What if you created a separate module called BaseComponent that defined the basic methods all component modules should have, and then in your custom components, include that BaseComponent.
Then, you should still be able to mixin those custom components into your ComponentContainer class.
Upvotes: 2