Rails concern and service object to refactor

Reading time ~1 minute

Rails concern

This is part of the code in Launch School 301 course. And in the code below, it shows how to extract the duplicate code in different module to ActiveSupport::Concern. But there are more than one way to refactor the code. DHH in the signal v. Noise wrote an article to introduce the concerns :

Different models in your Rails application will often share a set of cross-cutting concerns. In Basecamp, we have almost forty such concerns with names like Trashable, Searchable, Visible, Movable, Taggable.

Ryan Bates of Railscasts wrote an article to talk to people not to use concern. He encourage people to use Service Object.

  module Sluggable
    extend ActiveSupport::Concern
    included do
      before_save :generate_slug!
      class_attribute :slug_column

    def to_param

    def generate_slug!
      the_slug = to_slug(self.send(self.class.slug_column.to_sym))
      obj = self.class.find_by slug: the_slug
      count = 2
      while obj && obj != self
        the_slug = append_suffix(the_slug, count)
        obj = self.class.find_by slug: the_slug
        count += 1
      self.slug = the_slug.downcase

    def append_suffix(str, count)
      if str.split('_').last.to_i != 0
        return str.split('_').slice(0...-1).join('_') + '_' + count.to_s
        return str + '_' + count.to_s

    def to_slug(name)
      str = name.strip
      str.gsub!(/\s*[^A-Za-z0-9]\s*/, '_')
      str.gsub!( /_+/, "_")

    module ClassMethods
      def sluggable_column(col_name)
        self.slug_column = col_name

Is there more than one way to solve this problem?

Of course! The ActiveSupport::Concern was introduced in rails 4. After that, there are plenty ways to extract the duplicate code. One is also popular is use Service Object

So what is service object?

A service object (aka method object) performs one action. It holds the business logic to perform that action

It can not only refactor model but also controller! Besides, you can understand what each service object do(it is a class) better than in concern. And it can write a test to test the service object.

Read more on this article


to_param in Ruby on Rails

If I want a custom slug=======================I walk through this cutstom slug.1. create migration `add_slug` to add a column inside the...… Continue reading

What is ORM in Rails mean?

Published on July 14, 2017

Why use thin controller with fat model?

Published on June 29, 2017