Sha256: 9e270ae446c173828384803e44614725e847e3cbf8cb4e320b3c99fdb2793e5b

Contents?: true

Size: 1.33 KB

Versions: 2

Compression:

Stored size: 1.33 KB

Contents

module Rpub
  # Add tracking of subclasses to an existing class by extending it with
  # SubclassTracker.
  #
  # This allows you to set an identifier in a subclass using the `identifier`
  # macro, and find subclasses based on that value.
  #
  # Example:
  #
  #     class ParentClass
  #       extend SubclassTracker
  #     end
  #
  #     class ChildClass < ParentClass
  #       identifier 'foo'
  #     end
  #
  #     ParentClass.matching('foo') # => ChildClass
  #     ParentClass.matching('bar') # => raises SubclassTracker::NoSuchSubclass
  #
  # Note that you don't HAVE to set an identifier. If you don't, your child
  # class will never be found by `#matching`.
  module SubclassTracker
    class NoSuchSubclass < StandardError
      def initialize(subcommand)
        super "Unrecognized identifier: #{subcommand}"
      end
    end

    # Set or return the identifier for this class.
    def identifier(id = nil)
      return @identifier if id.nil?
      @identifier = id
    end

    def inherited(child)
      @subclasses ||= []
      @subclasses << child
      super
    end

    def each
      @subclasses ||= []
      @subclasses.each { |subclass| yield subclass }
    end

    def matching(identifier)
      find { |subclass| subclass.identifier === identifier } or raise NoSuchSubclass, identifier
    end

    include Enumerable
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
rpub-0.2.0 lib/rpub/subclass_tracker.rb
rpub-0.1.0 lib/rpub/subclass_tracker.rb