-
-
Save bjensen/799251 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Keeps a list of registered names associated with classes at a "base" class | |
#Example: | |
# | |
# class Base | |
# extend Registerable | |
# end | |
# | |
# class Foo < Base | |
# register :foo | |
# end | |
# | |
# class Bar < Base | |
# register :bar | |
# end | |
# | |
# Base.registered == {'foo' => Foo, 'bar' => Bar} | |
# Base.class_for(:foo) == Base::Foo | |
# Base::Foo.identifier == :foo | |
module Registerable | |
class NotRegisteredError < StandardError | |
end | |
#Create a registry on the class to which this module has been extended to contain | |
#a map of names to classes inheriting from it. | |
def self.extended(klass) | |
#All registered classes inheriting from klass are stores in a class | |
#instance variable on klass. | |
class << klass; def registered; @registered ||= {}; end; end | |
#Save the class using a closure, defining a singleton method on klass. | |
#User define_method to get the closure (block), but define_method defines | |
#instance methods on the receiver, so we need to get klass's metaclass first. | |
(class << klass;self;end).send(:define_method, :base){ klass } | |
end | |
def register(identifier) | |
base.registered[identifier.to_s] = self | |
end | |
def class_for(identifier) | |
base.registered[identifier.to_s] || raise(NotRegisteredError, "Couldn't find class registered with \"#{identifier}\"") | |
end | |
def create(identifier, *a, &b) | |
class_for(identifier).new(*a, &b) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment