Lesson 5
Dependency Management for Service Objects in Rails
Introduction to Dependency Management for Service Objects

Welcome back! By now, you have learned how to set up a Rails app, create controllers, and manage views. In our last lesson, we discussed service objects and how they help keep the business logic separate from controllers. When solving the previous practices, you may have noticed that in some cases we declared the data in many functions of the service instead of making it more structural. Today, we're taking this a step further by looking into dependency management for service objects in Rails. Effective dependency management ensures that our services are modular, testable, and easier to maintain.

What You'll Learn

In this lesson, we'll explore how to manage dependencies within service objects. Specifically, we’ll look at how to use dependency injection to make your services more flexible and easier to test. Using our SandwichService example, you'll learn the specifics of constructing services with dependencies and see how this design improves code maintainability.

Here’s a preview of the SandwichService class we'll be diving into:

Ruby
1class SandwichService 2 def initialize(bread: Bread.new, cheese: Cheese.new, grill: Grill.new) 3 @bread = bread 4 @cheese = cheese 5 @grill = grill 6 end 7 8 def make_sandwich 9 @grill.turn_on 10 bread_name = @bread.get_name 11 cheese_name = @cheese.get_name 12 @grill.turn_off 13 "Sandwich with #{bread_name} and #{cheese_name}" 14 end 15end

This SandwichService class illustrates a well-architected service object. It receives its dependencies (Bread, Cheese, and Grill) through initialization, promoting flexibility and easier testing.

Full Code Example

To understand how the SandwichService works in context, here is the complete code along with all the necessary files.

Sandwich Service Object

app/services/sandwich_service.rb

Ruby
1class SandwichService 2 def initialize(bread: Bread.new, cheese: Cheese.new, grill: Grill.new) 3 @bread = bread 4 @cheese = cheese 5 @grill = grill 6 end 7 8 def make_sandwich 9 @grill.turn_on 10 bread_name = @bread.get_name 11 cheese_name = @cheese.get_name 12 @grill.turn_off 13 "Sandwich with #{bread_name} and #{cheese_name}" 14 end 15end

Bread Dependency

app/services/bread.rb

Ruby
1class Bread 2 def get_name 3 "Whole Wheat" 4 end 5end

Cheese Dependency

app/services/cheese.rb

Ruby
1class Cheese 2 def get_name 3 "Cheddar" 4 end 5end

Grill Dependency

app/services/grill.rb

Ruby
1class Grill 2 def turn_on 3 puts 'Grill is on' 4 end 5 6 def turn_off 7 puts 'Grill is off' 8 end 9end

Usage_example (Controller or any place you use the service)

app/controllers/sandwiches_controller.rb

Ruby
1class SandwichesController < ApplicationController 2 def create 3 sandwich_service = SandwichService.new 4 @sandwich = sandwich_service.make_sandwich 5 render plain: @sandwich 6 end 7end

Routes

config/routes.rb

Ruby
1Rails.application.routes.draw do 2 resources :sandwiches, only: [:create] 3end
Why It Matters

Understanding dependency management in Rails is crucial for building scalable and maintainable applications. Good dependency management ensures that service objects are single-responsibility and can be reused across different parts of your application. It also makes the codebase easier to test, as dependencies can be mocked or stubbed during testing.

Benefits include:

  • Modularity: Keeping services modular makes it easier to update parts of your application without affecting others.
  • Testability: Injecting dependencies allows you to replace real objects with mocks or stubs, making unit tests more reliable and faster.
  • Maintainability: Clear separation of concerns and well-defined dependencies improve the readability and maintainability of your code.

By mastering dependency management for service objects, you will be able to write cleaner, more efficient, and easier-to-maintain code. Exciting, right? Let’s start the practice section and put these principles into action.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.