Impose interfaces on classes and let this gem automatically check that the interface constraints are met.
Add this line to your application's Gemfile:
gem 'interfaceable'
And then execute:
$ bundle install
In this example:
module Carrier
def call(number); end
def text(number, text); end
end
class Giffgaff
extend Interfaceable
implements Carrier
end
An attempt to load this code will result in the following error:
Giffgaff must implement: (Interfaceable::Error)
- Carrier#text
- Carrier#call
It will keep failing until Giffgaff
defines those methods.
Correctly! E.g.:
class Giffgaff
def call(number); end
def text(number, text = ''); end
end
Will fail because of method signature mismatch:
Giffgaff must implement correctly: (Interfaceable::Error)
- Carrier#text:
- expected arguments: (req, req)
- actual arguments: (req, opt=)
Classes may define additional optional or rest arguments.
module Carrier
def call(number); end
def text(number, text); end
end
class Giffgaff
def call(number, *opts); end
def text(number, text, opt1 = nil, opt2 = nil); end
end
This will not generate any errors since Giffgaff
implements the required methods with correct arguments only adding new optional ones.
Mix in Interfaceable
before any of the application code is loaded. For example, in the initializer. For extra peace of mind, you can noop interface checking in production:
# config/initializers/interfaceable.rb
class Class
if Rails.env.production?
def implements(*args); end
else
include Interfaceable
end
end