For example - If I have an application and I want to create an object that will be imported though a plugin, how would I go about writing that?
I've put together an example - It works as I'm intending; however I'm not sure if this is the 'conventional' way to go about it.
Is there a more efficient, or proper way to do this in Ruby?
start.rb
require './cloud.rb'
dir = 'plugins'
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
mycloud = CloudProvider.descendants.first.new
mycloud.say('testing')
cloud.rb
class CloudProvider
def self.descendants
ObjectSpace.each_object(Class).select { |asdf| asdf < self }
end
end
plugins/aws.rb
# This one inside plugins/
class AWS < CloudProvider
def initialize
end
def say(val)
puts val
end
end
Jekyll is a widely used Ruby project that provides plugins. I like their approach a lot:
Implement a base class that implements the basic functionality of your plugin (Jekyll has a few different types of classes you can inherit from).
Clearly specify what methods a subclass will have to override to make the plugin work.
Then you can have your user dump all their plugins in a plugins
directory and load all the files as you're doing now. This approach is built on solid OO concepts and it's very clean.
One suggestion: Ruby provides a inherited callback that you can use. This is much better than searching through all classes with asdf < self
.