Image for post
Image for post
Great service is priceless ;)

Essential RubyOnRails patterns — part 1: Service Objects

Błażej Kosmowski
Jun 13, 2017 · 6 min read

as seen by RubyOnRails Developers @ Selleo

Service objects (sometimes referred to as services) is a holy grail in Ruby On Rails development that helps to decompose your fat ActiveRecord models and keep your controllers slim and readable.

When to use Service Objects?

The pattern is so simple and powerful that it may become a bit overused in time; it is particularly useful when we need a place to define complex actions, processes with many steps, callbacks or interactions with multiple models which do not fit anywhere else. Service objects are also commonly used to mitigate problems with model callbacks that interact with external classes (read more…).

How to get most out of Service Object pattern?

#1 Stick to one naming convention

One of the most difficult tasks in programming is assigning things proper, self-explanatory names. There is a popular way to name service objects with words ending with “or”, i.e. UserCreator, TwitterAuthenticator, CodeObfuscator, etc. Sometimes such names may become a bit awkward, i.e., OrderCompleter. Therefore, I find naming service objects after commands or actions a bit more comprehensible. CreateUser, AuthenticateUsingTwitter, ObfuscateCode, CompleteOrder — it is clear what a given service object is responsible for. Regardless, try not to mix multiple naming conventions if you start using one. Be consistent.

#2 Do not instantiate service objects directly

We usually do not have much use for a service object instance other than just for executing a call method on it. If this is the case, consider using the following abstraction to shorten a notation of calling service objects:

Including this module will allow you to simplify the or notations into It is shorter and more readable. Still it leaves an option to instantiate the service object, which might be useful when we need to retrieve its internal state.

#3 Stick to one way of calling service objects

While I personally like using the call method, there is no particular reason not to use a different one (perform, run or execute are also good candidates). It is important though to always do it the same way, as our class name already states what the class responsibility is — there is no need to make it even more clear. The approach will relieve you from a burden of thinking about the right name every time you implement a new service object and will also be clear for other programmers how to use service object even without having a peek inside its implementation.

#4 Keep one responsibility per service object

This rule is somehow enforced by sticking to one way of calling a service object, yet it is not impossible to sneak in multiple responsibilities in such service objects as well. While service objects excel in orchestrating multiple actions, we should ensure that only one set of such actions is executed. An anti-pattern here might be to introduce e.g. the ManageUser service object, which would be responsible for creating and deleting users. Firstly, “Manage” does not say much; it is also not clear how to control which action should be executed. Introducing DeleteUser and CreateUser services instead makes the whole thing more readable and natural.

#5 Keep service objects constructors simple

It is a good idea to keep constructors simple in most of the classes we implement. Still, when our primary way of calling services is through the call class method, it might be even more beneficial to make constructor responsible for only saving arguments in service instance variables.


Not only can we focus on testing the call method rather than the constructor, but we can also draw a clear line between what can live in the constructor and what cannot do so. As developers we have to make a number of decisions everyday, why not take one off our plate by standardizing our approach.

#6 Keep the arguments of call methods simple

If more than one argument is provided to the service object, it might be reasonable to consider introducing keywords arguments to make those arguments more comprehensive. Even if service object accepts one argument only, using keyword argument might make it more readable as well, e.g.


#7 Return results through state readers

You will seldom need to retrieve information from your service objects. In case you needed to do so, there are a couple of ways you can approach this problem. A service object might return the result from its call method — for instance, returning true would indicate successful execution, while returning false would indicate failure. On the other hand, you create much more flexible solution when you make the call method return the service object itself. This way we can take advantage of reading service object instance state , e.g.

In some cases it is more effective to communicate edge cases which are unlikely to happen by raising exceptions instead, e.g.

#8 Focus on readability of your call method

The call method is the heart of your service object. It is a good practice to focus on making it as readable as possible — preferably just by describing the steps involved and reducing extra logic to the minimum. As an option, we can also control the flow of particular steps using and and or e.g.

#9 Consider wrapping call methods in transactions

Sometimes when multiple steps are involved to fulfill the responsibility of a service object, it might be a good idea to wrap the steps in a transaction, so that if any of the steps fails, we can always rollback the changes made in previous steps.

#10 Group service objects in namespaces

Sooner or later we will end up with tens of service objects. To improve code organization it is a good practice to group common service objects into namespaces. Those namespaces can group service objects by external services, high-level features or any other dimension we can think of. Still we need to keep in mind that the primary goal is to keep service object names and locations straightforward and readable. Sticking to one convention will allow you to quickly decide on the appropriate location — in this case leaving yourself fewer choices is a good thing.


A service object is a simple and powerful pattern which is easy to test and which has a wide area of use. The ease of implementing it is also a threat to keeping its implementation under control. Using concise convention when naming service objects, calling and getting results out of them consistently in the same way as well as keeping internals of service object classes simple and readable will ensure that your codebase will benefit from this pattern to a great extent.

If you feel you might need some simple abstraction around service object pattern, consider trying the BusinessProcess gem or consider a very similar Use Case pattern. An even thinner layer is provided by the rails-patterns gem.

Go to part 2 — Query Objects


Experienced Ruby On Rails, Elixir, Node.js,

Błażej Kosmowski

Written by

RubyOnRails craftsman @



Experienced Ruby On Rails, Elixir, Node.js, Ember.js, React & React Native developers ready to join your team or build your next project.

Błażej Kosmowski

Written by

RubyOnRails craftsman @



Experienced Ruby On Rails, Elixir, Node.js, Ember.js, React & React Native developers ready to join your team or build your next project.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store