ruby-on-railsarchitecturecontrolleranti-patternsservice-object

Rails service objects and controller


I have a colleague that likes to pass off the controller into a service object. For example a controller method might look the following way:

class FooController < ApplicationController

  ...

  def show
    Foo.new(self).call
  end

  ...

end

the service object looks like this then:

class Foo

  attr_reader :controller, :resource_id

  delegate :render, :params, :head, to: :controller

  def initialize(controller, resource_id)
    @controller = controller
    @resource_id = resource_id
  end

  def call
    resource = SomeActiveRecordModel.find(resource_id)
    if resource
      render json: resource.to_json
    else
      head :not_found
    end
  end

end

Somehow I feel that this is counterproductive and an instance of cargo-cult software engineering.

I would prefer to keep the service object completely separate from the controller. Dependencies would be passed into the service object's constructor, parameters would be passed into the service object as method arguments. Any result is simply returned from the method.

Sadly my colleagues are not exactly thrilled by this whenever I bring it up in a code review, which I in turn find relatively frustrating.

What are the pros an cons of the respective approaches? How can I argue my case better? Am I missing something here?


Solution

  • I suspect the answer is "it depends".

    In the exact example you gave, I see no particular advantage and it creates a degree of obfuscation. Also, in general, I agree with you on keeping the service object separate from the controller.

    However, there are times when I find myself passing the controller into the service object. For instance, when I have a lot of complex work to do in dynamically constructing a view.