class Hoodoo::Services::Service
Hoodoo::Services::Service
is subclassed by people writing service implementations; the subclasses are the entrypoint for platform services.
It’s really just a container of one or more interface classes, which are all Hoodoo::Services::Interface
subclasses. The Rack
middleware in Hoodoo::Services::Middleware
uses the Hoodoo::Services::Service
to find out what interfaces it implements. Those interface classes nominate a Ruby class of the author’s choice in which they’ve written the implementation for that interface. Interfaces also declare themselves to be available at a particular URL endpoint (as a path fragment); this is used by the middleware to route inbound requests to the correct implementation class.
Suppose we defined a PurchaseInterface and RefundInterface which we wanted both to be available as a Shopping Service:
class PurchaseImplementation < Hoodoo::Services::Implementation # ... end class PurchaseInterface < Hoodoo::Services::Interface interface :Purchase do endpoint :purchases, PurchaseImplementation # ... end end class RefundImplementation < Hoodoo::Services::Implementation # ... end class RefundInterface < Hoodoo::Services::Interface interface :Refund do endpoint :refunds, RefundImplementation # ... end end
…then the entire Service
subclass for the Shopping Service
could be as small as this:
class ShoppingService < Hoodoo::Services::Service comprised_of PurchaseInterface, RefundInterface end
Names of subclasses in the above examples are chosen for clarity and the naming approach indicated is recommended, but it’s not mandatory. Choose choose whatever you feel best fits your code and style.
Conceptually, one might just have a single interface per application for very small services, but you may want to logically group more interfaces in one service for code clarity/locality. More realistically, efficiency may dictate that certain interfaces have such heavy reliance and relationships between database contents that sharing the data models between those interface classes makes sense; you would group them under the same service application, sacrificing full decoupling. As a service author, the choice is yours.
Public Class Methods
Return an array of the classes that make up the interfaces for this service. Each is a Hoodoo::Services::Interface
subclass that was registered by the subclass through a call to comprised_of.
# File lib/hoodoo/services/services/service.rb, line 86 def self.component_interfaces @component_interfaces end
Protected Class Methods
Called by subclasses listing one or more Hoodoo::Services::Interface
subclasses that make up the service implementation as a whole.
Example:
class ShoppingService < Hoodoo::Services::Service comprised_of PurchaseInterface, RefundInterface end
See this class’s general Hoodoo::Services::Service
documentation for more details.
# File lib/hoodoo/services/services/service.rb, line 123 def self.comprised_of( *classes ) # http://www.ruby-doc.org/core-2.2.3/Module.html#method-i-3C # classes.each do | klass | unless klass < Hoodoo::Services::Interface raise "Hoodoo::Services::Service::comprised_of expects Hoodoo::Services::Interface subclasses only - got '#{ klass }'" end end # Add the classes from this call to any given in a previous call. @component_interfaces ||= [] @component_interfaces += classes @component_interfaces.uniq! end
Public Instance Methods
Since service implementations are not pure Rack
apps but really service middleware clients, they shouldn’t ever have “call” invoked directly. This method is not intended to be overridden and just complains if Rack
ends up calling here directly by accident.
env
-
Rack
environment (ignored).
# File lib/hoodoo/services/services/service.rb, line 104 def call( env ) raise "Hoodoo::Services::Service subclasses should only be called through the middleware - add 'use Hoodoo::Services::Middleware' to (e.g.) config.ru" end
Instance method which calls through to ::component_interfaces
and returns its result.
# File lib/hoodoo/services/services/service.rb, line 93 def component_interfaces self.class.component_interfaces end