In order to use methods from ProcessBase
in the body of class MatchStuff
, you can extend
it in addition to include
ing or subclassing it:
class MatchStuff
include ProcessBase
extend ProcessBase
match 'account' do |event|
pp event
end
end
But then you have the problem that @match_code
refers to a class instance variable in match
, but a regular instance variable in accept
. I'd add a reader method to ProcessBase
and use it on the class in accept
, so you always use the class instance variable. Then you can use ||=
to avoid needing the initialize
method (which won't get called for the class when you extend
).
module ProcessBase
# reader method, autovivifying to empty Array
def match_code
@match_code ||= []
end
def match(string_match, &block)
# using the reader here, on self, which is the class
match_code.push([string_match, block])
end
def accept(test_str)
# here, self is the instance, so we have to explicitly get the class
# and access match_code from there
self.class.match_code.each do | test_block |
if test_str == test_block[0])
test_block[1].call test
end
end
end
end
Alternatively, you could put match
(with the match_code
reader) and accept
in separate modules, extend
one and include
the other. That has the advantage of not giving your instances a match
method that doesn't work (because it uses the wrong match_code
). You could even define an included
or extended
method that does one when you do the other.
module ProcessClassBase
def match_code
# as above
end
def match
# as above
end
end
module ProcessInstanceBase
def accept
# as above
end
def included(other_mod)
other_mod.extend(ProcessClassBase)
end
end
class MatchStuff
include ProcessInstanceBase # now this also extends ProcessClassBase
match 'account' do |event|
pp event
end
end
It's probably worth noting that this all breaks if you subclass MatchStuff
. Instances of the subclass (call it MatchStuffSub
), when accept
is called, will try to access MatchStuffSub.match_code
instead of MatchStuff.match_code
(where match
puts stuff).