Skip to content

Instantly share code, notes, and snippets.

@nunosilva800
Created March 5, 2019 16:50
Show Gist options
  • Save nunosilva800/87302eb88f637c80b9a4cb884839e9d0 to your computer and use it in GitHub Desktop.
Save nunosilva800/87302eb88f637c80b9a4cb884839e9d0 to your computer and use it in GitHub Desktop.
service objects in rails

Service Objects

Service Objects are classes or modules that have one public method, often named #call, and are designed to perform a single task or service.

Service objects are single business actions.

Example:

As a class

class ServiceObject
  def call(arg1, arg2, ...etc)
    new(arg1, arg2, ...etc).call
  end

  def initialize(arg1, arg2, ...etc)
    @var = arg1
    @var = arg2
    ...etc
  end

  private

  def call
     # Logic goes here
  end
end

As a module

module ServiceObject
  def self.call(arg1, arg2, ...etc)
   # Logic goes here
  end
end

When Should I Not Use a Service Object?

  • Does your code handle routing, params or do other controller-y things? If so, don’t use a service object—your code belongs in the controller.

  • Are you trying to share your code in different controllers? In this case, don’t use a service object—use a concern.

  • Is your code like a model that doesn’t need persistence? If so, don’t use a service object. Use a non-ActiveRecord model instead.

  • Is your code a specific business action? (e.g., “Take out the trash,” “Generate a PDF using this text,” or “Calculate the customs duty using these complicated rules”) In this case, use a service object. That code probably doesn’t logically fit in either your controller or your model.

When Should I use a Service object?

  1. Only One Public Method per Service Object We should choose the name of this method: .call, .perform, .run, .execute, etc.

  2. Name Service Objects Like Dumb Roles at a Company TweetReader, TweetCreator, EventsManager::Create, EventsManager::Update, EventsManager::Finder,...

  3. Don’t Create Generic Objects to Perform Multiple Actions

  4. Handle Exceptions Inside the Service Object

Important team decisions

  1. Name of the public method. We can then define services that inherit from this class:
# app/services/application_service.rb
class ApplicationService
  def self.call(*args, &block)
    new(*args, &block).call
  end
end
  1. Any constrains on the allowed return values? A boolean, a value, an enum, an object with result status?

References

In favour:

Against:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment