<commit_before>---
layout: post
title: Wrangling Service Objects with method_struct
---

Service Object is a pattern of extracting business logic into a separate "service". It has gotten considerable traction in the Ruby ecosystem and is worth exploring. <NAME> [described Service Objects in the following way](http://stevelorek.com/service-objects.html):

> A 'service' describes system interactions. Usually, these will involve more than one business model in our application.

> As an example; we have a User model and this encapsulates a password. If a user has forgotten their password, the business rules dictate that we have to send them an e-mail with a link to reset it. This functionality is a service.

The CodeClimate [blog post on refactoring fat models](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/) has a good rulebook on when to use this pattern:

> * The action is complex (e.g. closing the books at the end of an accounting period)
> * The action reaches across multiple models (e.g. an e-commerce purchase using Order, CreditCard and Customer objects)
> * The action interacts with an external service (e.g. posting to social networks)
> * The action is not a core concern of the underlying model (e.g. sweeping up outdated data after a certain time period).
> * There are multiple ways of performing the action (e.g. authenticating with an access token or password). This is the Gang of Four Strategy pattern.

I see Service Objects as a mutation of the Command pattern. They allow separation of business logic from models and controllers, but have further benefits in testing and composition.

### Hello method_struct

At Base CRM, we're implementing Service Objects using the [method_struct](https://github.com/basecrm/method_struct) gem. Let's go through an example which illustrates the benefits of this approach.

Consider the following example. We have a blog app with a Post model, having a title and body attributes. Let's look at the create method in the Posts controller:

{% highlight ruby %}
# app/controllers/posts_controller.rb
class PostsController < ApplicationController

  def create
    @post = Post.new(post_params)

    if @post.save
      twitter = TwitterClient.new(current_user)
      twitter.tweet "Blogged: #{@post.title}"

      search = SearchClient.new
      search.index @post

      redirect_to @post, notice: 'Post was successfully created.'
    else
      render :new
    end<commit_msg>Add a separator to Wrangling post<commit_after>---
layout: post
title: Wrangling Service Objects with method_struct
---

Service Object is a pattern of extracting business logic into a separate "service". It has gotten considerable traction in the Ruby ecosystem and is worth exploring. Steve Lorek [described Service Objects in the following way](http://stevelorek.com/service-objects.html):

> A 'service' describes system interactions. Usually, these will involve more than one business model in our application.

> As an example; we have a User model and this encapsulates a password. If a user has forgotten their password, the business rules dictate that we have to send them an e-mail with a link to reset it. This functionality is a service.

The CodeClimate [blog post on refactoring fat models](http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/) has a good rulebook on when to use this pattern:

> * The action is complex (e.g. closing the books at the end of an accounting period)
> * The action reaches across multiple models (e.g. an e-commerce purchase using Order, CreditCard and Customer objects)
> * The action interacts with an external service (e.g. posting to social networks)
> * The action is not a core concern of the underlying model (e.g. sweeping up outdated data after a certain time period).
> * There are multiple ways of performing the action (e.g. authenticating with an access token or password). This is the Gang of Four Strategy pattern.

I see Service Objects as a mutation of the Command pattern. They allow separation of business logic from models and controllers, but have further benefits in testing and composition.

### Hello method_struct

At Base CRM, we're implementing Service Objects using the [method_struct](https://github.com/basecrm/method_struct) gem. Let's go through an example which illustrates the benefits of this approach.

<!-- more -->

Consider the following example. We have a blog app with a Post model, having a title and body attributes. Let's look at the create method in the Posts controller:

{% highlight ruby %}
# app/controllers/posts_controller.rb
class PostsController < ApplicationController

  def create
    @post = Post.new(post_params)

    if @post.save
      twitter = TwitterClient.new(current_user)
      twitter.tweet "Blogged: #{@post.title}"

      search = SearchClient.new
      search.index @post

      redirect_to @post, notice: 'Post was successfully created.'
    else
      render :new
    end
{'fraction_non_alphanumeric': 0.06689297124600639, 'fraction_numerical': 0.003594249201277955, 'mean_word_length': 4.095625635808749, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 19, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3227597', 'n_tokens_mistral': 1313, 'n_tokens_neox': 1227, 'n_words': 654}