This is an example of how I combine interaction/service classes with Wisper event broadcasting in Rails.
In this example, I show a UsersController#create
API, a corresponding service object, and all the test code/listeners to make it all happen.
The outcome is:
- Concepts in your system ("Signing up a user", "Creating an order") have a single entry point in your codebase, vs. making raw ActiveRecord calls to
object.save
in dozens of places. - Since your concept has one entry point (the service class), you can easily
grep
for usage of it. - Stupid easy to attach listeners to the service class
- All event listeners are very small and easily unit tested
- Controllers have zero
if/else
logic and are very dumb - Unit tests stay fast
- Acceptance tests still exercise the whole system, including event listeners
- Plain old Ruby objects rule
I agree with Kris. I would look into temporary global subscribers, which I find to be the best balance between global DRYness and flexability. For example you could always attach all of your common listeners to all web requests like so:
Another thing that I do is make it possible to easiliy attach listeners to each test case, so that when I'm not running my accceptance tests I can still whitelist which listeners should be attached on a per test level.
rails_helper.rb:
Note that in my last example I have a
Listeners
class which is a helper class that I use for easily subscribing groups of listeners. Hopefully you get the idea.