Refactoring Rails Controllers with Interactors: More Clarity, Less Coupling

In a recent Ruby on Rails project, I came across controllers overloaded with responsibilities: business logic, validations, side effects, and conditionals all mixed together.
It made testing hard, onboarding slower, and changes risky.

To improve this, I proposed and implemented a transition to Interactors, focusing on single responsibility and step composition.


The Impact


Before

class UsersController < ApplicationController
  def create
    user = User.new(user_params)

    if user.save
      EmailConfirmationService.send_confirmation(user)
      Analytics.track("user_created", user_id: user.id)
      redirect_to root_path, notice: "Account created. Please check your email."
    else
      flash[:error] = user.errors.full_messages.to_sentence
      render :new
    end
  end

  private

  def user_params
    params.require(:user).permit(:email, :password, :name)
  end
end

After:

class UsersController < ApplicationController
  def create
    result = CreateUser.call(params: user_params)

    return redirect_to root_path, notice: "Account created. Please check your email." if result.success?

    flash[:error] = result.error
    render :new
  end

  private

  def user_params
    params.require(:user).permit(:email, :password, :name)
  end
end
# app/interactors/create_user.rb
class CreateUser
  include Interactor

  def call
    user = User.new(context.params)

    if user.save
      EmailConfirmationService.send_confirmation(user)
      Analytics.track("user_created", user_id: user.id)
      context.user = user
    else
      context.fail!(error: user.errors.full_messages.to_sentence)
    end
  end
end

Final Thoughts

Refactoring isn’t just about writing cleaner code — it’s about building systems that are easier to understand, test, and evolve.
In my experience, introducing Interactors in legacy or monolithic Rails apps has been a reliable way to regain control over complexity while improving the development experience for everyone on the team.


Tags

#RubyOnRails #Interactor #Refactoring #SoftwareEngineering #CleanCode #BackendDevelopment