Using service objects with CRUD interface, the smart way
ruby rails crud_responderIn a previous post we saw how to create service objects with CRUD interface. Now let’s see why you should care it is useful.
REST architecture is about CRUD over http. Rails uses RESTful routes. And in every RESTful controller action you may find something like this:
Not very DRY, isn’t it? The only differences between these actions are:
- Method called on a model
- Action on success
- Action on error
- Text in flash message on success
- Text in flash message on error
What if we can extract them? We can decide which method to call on a model, where to redirect/render after, which flash messages to show by inspecting the model itself and a controller’s action.
But this is fine when you are dealing with ActiveRecord
(ActiveModel
to be precise) models. What if we are using service objects? One of the “canonical” way to use service objects is by calling call
method, like this:
Again, not very DRY. And here comes services which behave like ActiveModel
and use CRUD interface.
Also, let’s add some magic
method which will call appopriate method on an object, redirect and show flashes:
What inside magic
function?
- Check which actions it is called from by inspecting
caller
- Call
save
ordestroy
according to the action - Redirect to appropriate url or render a template according to result of calling
save
ordestroy
- Show appropriate flash messages. In case of error - extract messages from
errors
object
Not so magic, isn’t it? Luckily you don’t have to implement all this logic because I’ve already done this in crud_responder gem.
Now it’s very handy to have all domain objects (models and services) with CRUD interface so you can use them in controllers without worrying whether it’s ActiveRecord model or a service object.