Reputation:
What I want is a single API which determines the class to delegate methods to based on a parameter passed through initializer. Here is a basic example:
module MyApp
class Uploader
def initialize(id)
# stuck here
# extend, etc. "include Uploader#{id}"
end
end
end
# elsewhere
module MyApp
class UploaderGoogle
def upload(file)
# provider-specific uploader
end
end
end
My desired outcome:
MyApp::Uploader('Google').upload(file)
# calls MyApp::UploaderGoogle.upload method
Please be aware the above is for demonstration purposes only. I will actually be passing an object which contains an attribute with the uploader id. Is there a better way to handle this?
Upvotes: 0
Views: 41
Reputation: 1171
Haven't tested it, but if you want to include
a module:
module MyApp
class Uploader
def initialize(id)
mod = ("Uploader"+id).constantize
self.send(:include, mod)
end
end
end
If you want to extend your class with a module:
module MyApp
class Uploader
def initialize(id)
mod = ("Uploader"+id).constantize
self.class.send(:extend, mod)
end
end
end
Upvotes: 1
Reputation: 3641
Sounds like you want a simple subclass. UploaderGoogle < Uploader
Uploader defines the basic interface and then the subclasses define the provider specific methods, calling super as necessary to perform the upload. Untested code OTTOMH below…
module MyApp
class Uploader
def initialize(id)
@id = id
end
def upload
#perform upload operation based on configuration of self. Destination, filename, whatever
end
end
class GoogleUploader < Uploader
def initialize(id)
super
#google-specific stuff
end
def upload
#final configuration/preparation
super
end
end
end
Something along those lines. To base this on a passed parameter, I'd use a case
statement.
klass = case paramObject.identifierString
when 'Google'
MyApp::GoogleUploader
else
MyApp::Uploader
end
Two things: If you do this in several places, probably extract it into a method. Second, if you're getting the input from the user, you've got a lot of anti-injection work to do as well if you, for instance, create a class name directly from a provided string.
Upvotes: 1