I have a design problem which I can't think up an elegant solution for. I'm writing a background job in my rails app which means that my job class (MyJobClass) must inherit from a certain parent job class (ParentJobClass). My job will need to have the same methods, however the implementation of some of those methods will need to be different depending on the value of a parameter which is passed in during the instantiation of my job class.
Because MyJobClass is already inheriting from ParentJobClass I don't get how to get multiple implementations of the same method.
I was thinking of something like a conditional mixin of a module containing the specific implementations. However I'm not sure if that's a possible since it would be conditional on a parameter that's passed in during instantiation. E.g. something like...
class ParentJobClass
end
class MyJobClass < ParentJobClass
case @p1
when 'text'
include TextTips
when 'image'
include ImageTips
when 'video'
include VideoTips
end
def initialize(p1)
@p1 = p1
end
end
You are correct that they way you have it will not work because it relies on an instance variable that is out of scope. (@p1
in the context of the class will always be nil
)
While you would probably be better off implementing specific sub-classes (or just standalone classes depending on implementation), as it would be more communicative, technically speaking you can include
those modules specific to the eigenclass of the instance. Meaning:
class MyJobClass < ParentJobClass
MODS = {'text' => TextTips, 'image' => ImageTips, 'video' => VideoTips}.freeze
def initialize(p1)
@p1 = p1
singleton_class.include(MODS[p1]) if MODS.key?(p1)
end
end
Or use dependency injection for the same
class MyJobClass < ParentJobClass
def initialize(p1, mod=nil)
@p1 = p1
singleton_class.include(mod) if mod.class == Module
end
end
MyJobClass.new('text',TextTips)
By way of simplified example:
class Foo
def initialize(mod=nil)
singleton_class.include(mod) if mod
end
def hello = 'hi'
end
module Portuguese
def hello = 'olá'
def goodbye = 'adeus'
end
a = Foo.new
a.hello #=> 'hi'
a.goodbye #=> NoMethodError
b = Foo.new(Portuguese)
b.hello #=> 'olá'
b.goodbye #=> 'adeus'