SubclassMustImplement

There are circumstances when it is desirable to specify certain methods as abstract, i.e. it is the responsibility of any subclass to implement them. Getting a MethodMIssing is not helpful; an error that explicitly explains that the missing method is required by contract to fully implement the interface will save much time and frustration.

Installation

Add this line to your application's Gemfile:

gem 'subclass_must_implement'

And then execute:

$ bundle

Or install yourself as:

$ gem install subclass_must_implement

Usage

Either include SubclassMustImplement or extend SubclassMustImplement in your base class. Then call subclass_must_implement with a list of required method names as symbols. You can optionally pass in a custom error message using the err_message named argument.

Example 1:

class BaseFoo
  include SubclassMustImplement

  subclass_must_implement :foo, :bar, :baz
end

class Foo < BaseFoo
  def foo
    :foo
  end
end

f = Foo.new
f.foo # returns :foo
f.bar # raises a NotImplementedError that "bar" must be implemented in the subclass
f.baz # raises a NotImplementedError that "baz" must be implemented in the subclass
f.qux # raises a MethodMissing

Example 2:

class BaseBar
  extend SubclassMustImplement

  subclass_must_implement :foo, :bar, err_message: "Version expected!!!"
end

class Bar < BaseBar
  def bar
    :bar
  end
end

b = Bar.new
b.bar # return :bar
b.foo # raises a NotImplementedError with the specified error message "Version expected!!!"

Using With RSpec

There is a custom RSpec matcher included to simplify testing.

Example:

# NOTE: depending on gem load order, you may need to manually load the matcher.
# If so, add the following line to your `spec_helper.rb`
require "subclass_must_implement/rspec_matcher/require_subclass_to_implement_matcher"

# Given the following class:
class BaseBar
  extend SubclassMustImplement

  subclass_must_implement :foo, :bar, err_message: "Version expected!!!"
end

# Test to ensure required functionality is specified:

# Custom error messages can be specified
it { expect(BaseBar).to require_subclass_to_implement(:version).with_error_message("Version expected!!!")}

# Either the class or the instance can be passed to the matcher
it { expect(BaseBar.new).to require_subclass_to_implement(:sub_version) }

# Sometimes it makes sense to specify certain methods as not required
it { expect(BaseBar).to_not require_subclass_to_implement(:foo) }

Contributing

  1. Fork it ( https://github.com/[my-github-username]/subclass_must_implement/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request
  6. Make sure all the test pass and your changes have test coverage!