Accord - object interfaces and adaptation for Ruby
Accord is a gem providing basic object interface and adaptation support for Ruby. An interface represents a protocol or contract (an API), and this gem allows you to label your objects/classes/modules as being compliant with a given API by declaring them as implementing/providing interfaces. Thus, one would call this an implementation of ‘Design by Contract <en.wikipedia.org/wiki/Design_by_contract>`_ in Ruby.
Object adaptation is also supported. Given an object which claims to provide some API, and in a specific point of the code another API is needed, Accord will allow adapting from the object API to the desired one (provided that an adapter which can adapt the APIs is known by Accord).
This gem was largely inspired by the Python package “zope.interface“, maintained by the ‘Zope Toolkit Project <docs.zope.org/zopetoolkit/>`_. “zope.interface“ source `can be found here <github.com/zopefoundation/zope.interface>`_.
Disclaimer: this is not used in any real world project yet. The API is still changing (and will, while this gem is not in the 1.0 version). Not ready for prime time.
Basic usage
- Declare some interfaces
-
Labelled = Accord::Interface(:Labelled) do
responds_to :label
end PersonAPI = Accord::Interface(:PersonAPI)
- Implement them
-
class Person
attr_reader :name def initialize(name) @name = name end
end
class PersonLabel
def initialize(person) @person = person end def label @person.name end
end
- Declare that your classes are implementations of the interfaces
-
Accord::Declarations.implements(Person, PersonAPI) Accord::Declarations.implements(PersonLabel, Labelled)
Tell Accord that people can have labels (that is, they can be adapted to
- ‘Labelled`)
-
Accord.default_adapter_registry.register(, Labelled) do |person|
PersonLabel.new(person)
end
- Now, in a piece of code which needs a label
-
def show(object)
Labelled.adapt!(object).label
end
- When a person is given to ‘#show`, its name will be used to provide a label
-
person = Person.new(‘John’) show(person) #=> ‘John’
By registering more adapters, ‘#show` can be reused to show the labels of other types of objects, without changing its source. `#show` doesn’t rely on receiving a person, but depends only on an interface. Also, everything could have been added in the application after the ‘Person` class (as if that class were legacy code), without modifying its source. Or `Person` could be a class in a third party library.
License
This gem is MIT-licensed. See LICENSE.txt in the root of this repository.