Setsuzoku
We found ourselves writing lots of 3rd-party integration code that started to look really similar (lots of common API call, credential management and error handling logic). Additionally, we found that our application code was becoming too strongly coupled to a specific 3rd-party implementation. Heavily relying on the structures and conventions of a payment platform for instance, making our reliance on that vendor inseverable.
Our solution was to build a generic interface layer between 3rd-party services and a ruby application.
Setsuzoku lets you build and use plugins that can generically define behaviors expected with a 3rd party service.
As an example: the first plugin we built was a mobile/sms plugin. It defines generic API actions for the application to consume. E.g. send_message, search_local, search_toll_free. With these defined and your application configured to use this generalized plugin API adding a 3rd-party vendor implementation becomes much cleaner. All a new mobile/sms plugin is required to do is define its API actions, endpoints and any vendor-specific mapping required to normalize the requests and response. This way your application can interact with a plugin agnostic of how the plugin implements its methods under the hood. Meaning if you're using one 3rd-party vendor and want to replace it, you simply create the new plugin, implement the methods you want and swap it out.
To ensure plugins are holding up their end of the bargain the base plugin of a business use-case, e.g. billing/sms etc can define a spec for each API action it wants implemented. If a plugin implements this action it must satisfy the test's expectations.
Additionally, application code that relies on plugins has its data stubbed without relying on the evaluation of the plugin's code. To ensure the stubbed data upholds its contract we also test that the plugin's stub definition satisfy the data contract.
This ensures a base plugin has properly stubbed its data for application testing, and any implementation plugin has properly implemented the actions it chooses to implement.
Usage
Any class in your application can register a plugin. By registering a plugin a class has established that is has dependence on a third-party service and would like off-load the busy work of interfacing to the plugin. To correctly register a plugin, often, a credential must be provided, as well as plugin specific parameters.
Once registered your integration to the generic 3rd-party service should be pretty seamless and well decoupled from your application.
Our general practice as an example is this:
First we define a base application class that will consume the plugin api actions. This should handle all logic and be able to interface w/ all plugins such that the code here is generic, and any changes should happen in the plugin implementations.
MobileIntegration < ApplicationRecord
# Application work to do when sending a message
def send_message(body)
#this resp is generic regardless of the plugin
resp = plugin.send_message(body)
notify_customer(resp) if resp.success
end
....
end
Then we define 2 service specific implementations that will register plugins. You will also need to specify credential, and instance level methods here.
FirstMobileIntegration < MobileIntegration
self.register_plugin(plugin_class: Setsuzoku::FirstMobilePlugin)
end
SecondMobileIntegration < MobileIntegration
self.register_plugin(plugin_class: Setsuzoku::SecondMobilePlugin)
end
Now, as long as your application is getting an instance of the correct plugin.
E.g. your application knows when to use FirstMobileIntegration
vs SecondMobileIntegration
setsuzoku plugins should handle the request mapping/request transmission/response parsing/response mapping
and return your application a nicely formatted exception handled response. Now your application can interface with
all these 3rd-parties in a simple to understand and common way.
Installation
Add this line to your application's Gemfile:
gem 'setsuzoku'
And then execute:
$ bundle
Or install it yourself as:
$ gem install setsuzoku
Contributing
License
The gem is available as open source under the terms of the MIT License.