Services, What I Wish I learned As A New Rails Developer

Joey Byrne
Aug 22, 2017 · 3 min read

Services are what gives rails app functionality in clear, clean control patterns. We use services at Redrooffs for structuring functionality in the apps we build with plain ruby objects. Services act as “action objects”, with methods that perform, as they’re named actions. Think of actions like notifying a slack channel, sending an email, subscribing to an email list. Services can also be used for triggering a larger, more complex series of actions in your app such as a registration process, or payment flow. As a new developer I was taught to build RESTful routes, and to push methods down the stack, resulting in most of my app logic living in the model layer. As you become more comfortable with the rails development pattern you’ll start to notice a consistent theme of “where should I put this code?”. Let me answer that question for you… make it into a service.

How to Get Started Using services

As I mentioned before services are simple Ruby Objects. This means that they are independant of the rails cycle. You don’t need to follow the standard rails inheritance pattern or use any external libraries to make services work (although they certainly can and often do use them). Services can be as simple as separating the sending of an email from a controller or as complicated as a payment, slack notification, mobile notification system. Rails is wonderful because it automatically detects the new Ruby objects created in the App folder. This means, there’s no need for require statements to include your services into the rails pipeline. To add and organize your services simply create a services folder in the App directory of your system and restart your rails server. Boom they’re ready to go.

App/ 
- Assets
- Channels
- Controllers
- Helpers
- Jobs
- Mailers
- Models
- Services
- Views

Actually using a service

Okay, your service folder is ready to go. Now it’s time to set up and use your services. For this example, we’ll be using the Mailchimp API wrapped by the Gibbon gem to add a person to a mailing list. Here is our service, what we’re going to do, it create the service object, a method to initiate the API call and a public method to initiate the API call from our controller.

require "gibbon" Class SubscriptionService 

def initialize(params)
@user_to_subscribe = params[:new_subscription]
end
def perform
subscribe_to_list
end
private def subscribe_to_list
gibbon.lists(ENV["MAILCHIMP_USER_LIST"]).members.create(body: {email_address: @user_to_subscribe.email, status: "Subscribed", merge_fields: {FNAME: @user_to_subscribe.first_name, LNAME: @user_to_subscribe.last_name}})
end
end

As you can see above, we’ve created a simple ruby object calling it SubscriptionService that takes a new subscription object. A method that extracts the gibbon gem new subscriber method and lastly exposes a method to start the subscribe request. Now it’s as easy as creating the new service object in a controller and calling the perform method from your controller. In the example below we’re going to automatically sign up new users to our new user mailing list.

Class UserController > ApplicationController    ...    def create 
@user = User.create(user_params)

if @user.save
...
SubscriptionService.new({new_subscription: @user}).perfom
...
else
...
end
...
end
... end

Do you see how simple that is, and how clean that controller code looks now?

Clean up and Summary

We’ve structured this service, with a terrible naming scheme. To clean it up we will namespace the service into a MailChimp specific name, we’ll call it MChimp (mostly because i’m pretty sure MailChimp is a reserved module name from the gibbon gem). To do this, we will create a MChimp folder within the Services folder.

App/ 
- Assets
- Channels
- Controllers
- Helpers
- Jobs
- Mailers
- Models
- Services/
- MChimp
- Views

We’ll update the SubscriptionService class to:

require "gibbon" module MChimp 

class SubscriptionService
...
#same code as before
...
end
end

We’ll update our User Controller to use the name spaced Subscription Service class.

Class UserController > ApplicationController   ...   def create 
@user = User.create(user_params)

if @user.save
...
MChimp::SubscriptionService.new({new_subscription: @user}).perfom
...
else
...
end
...
end
...end

There we go, we’ve got a nicely cleaned up module we can add other service objects to, for maybe recalling the list and doing something with it. Service objects can be immensely powerful and once you’ve taken the time to learn their development partner you will fall in love as I have.

Happy coding.


Originally published at www.theredrooffs.com.

)
Joey Byrne

Written by

Computer Nerd | Weekend Warrior | Tech excites me | #Vancouver

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade