What’s in the ebook? 

Step by step recipes that you can apply to improve your controllers. 

Fearless Refactoring is a practical guide to writing small, maintainable, and pleasing Rails controllers.

It shows the usual problems with intertwining business process logic and HTTP concerns. It demonstrates ways to decouple those two so they can evolve separately. That makes your app easier to understand and easier to test.

Buy now
180 pages + 50 pages of bonus material.



This 180-page e-book will teach you everything you need to know to make your controllers look better, your code be more maintable and pleasureful to work with.

Hi, I'm Andrzej Krzywda, the founder and CEO of Arkency, a Rails consultancy. I spend time reviewing dozens of legacy Rails apps every year, finding patterns, applying fixes. I care about code quality, maintainability and explicitness.

For 5 years I've been teaching Rails at the University of Wrocław in a way that shows my students the beauty and speed of delivering Rails applications, as well as the mess that they can sometimes turn into. Working with students have taught me patience and how to structure my knowledge so it is easily digestible.

I live in a small village near Wrocław in Poland, with two kids and my wife. As almost everyone in Arkency I work remotely from home.




Good tests tell a story

Unit tests vs class tests

Service objects as a way of testing Rails apps

Service controller communication

Naming Conventions

Where to keep services

Routing constraints

Rails controller - the lifecycle

Bonus: Pretty, short urls for every route in your app

Bonus: How RSpec helped me with resolving
random spec failures

Bonus: Private classes in Ruby

Bonus: Domain Events over Active Record Callbacks

Bonus: Implementing & Testing SOAP API clients

Bonus: Fluent Interfaces in Ruby ecosystem

Copyright 2017 Arkency

Michał Taszycki

Señor Software Developer at GunpowderLabs

"Fearless Refactoring - Rails Controllers" by Andrzej Krzywda is a great resource for everyone who at least once encountered legacy Rails application.

With good examples, refactoring techniques, and step by step guides it is a worthy read for novices and intermediate developers. Even if you are an expert, the book will save you time by giving you tested solutions for dealing with legacy Rails apps.

Michael Matyas

senior developer at Untitled Kingdom

“Fearless Refactoring helped me embrace the simplicity and powerfulness of service objects and lean controller code. Ever since I've started using exception-based control flow my code became much more readable and fun to work with. 10/10 would recommend.”

Are your controllers looking like this?

Coding an app in Rails is always fun... for the first 3 months.

After some time, small, little things show up. The tests are no longer below 1 minute. Thin controllers are not really so thin anymore. Single Responsibility Principle is more of a not-so-funny joke than something that you can apply to your Rails models.

The build is taking so long at your machine, that you've almost automated it to immediately open Twitter, gmail, FB, HackerNews because nothing else can be done during the tests.

The speed of adding features slows down. It's no longer fun to demonstrate new features to the Customer.

Your development plan for this release sounds so great. The users could be so happy with the new features. Your code could be so elegantly designed.

Is this really all you did this week?

"Can we agree that we keep controllers thin?" - the team starts to have those little arguments. The model callbacks are killing you. They started simple and now you just keep adding the conditionals.

How can we unit test if it's all coupled together?

You'd love to unit test your models and controllers, but something doesn't feel right about the endless section of mocks, stubs. User.should_receive(this), should_receive(that). It feels like repeating the code. What's the point of such tests?

How do other Rails developers deal with such problems? Rails conventions are great at the start, after that you're on your own.

This shouldn't be so hard!

What if you could have speedy and intuitive conventions even after the app grew over time?

If you had conventions, you would spend less time moving code from one place to another, hoping that you will hide it somewhere. Less time arguing in the team means more features being delivered. More features means happy customers. We want to have happy users and customers.

What if you could add features as fast as at the start?

Fearless Refactoring: Rails Controllers - the book

It's possible to have the same speed of delivering features over time and the "Fearless Refactoring: Rails Controllers" book will teach you how.

This book contains a distilled knowledge taken from reliable architectures, like DDD, Hexagonal Architecture, DCI. I spend years researching those topics with one goal.

Make your application better, simply, step-by-step, under control.

I took what's best from the popular architectures, got rid of things that don't fit well with the Rails specifics and prepared recipes how to deal with a messy Rails code.

Who has time to stay on top of all the latest articles, ideas, and code samples? You need good, working, easy to change code.

This book is a step-by-step guide how to introduce a service layer in your existing Rails app. Every step is described in every detail, with code changes. All of that, so that you can safely refactor your codebase, even without a full test coverage.

Buy now for $49 in PDF, epub and mobi.

class IssuesController < ApplicationController
  default_search_scope :issues
  before_filter :find_issue, :only => [:show, :edit, :update]
  before_filter :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
  before_filter :find_project, :only => [:new, :create, :update_form]
  before_filter :authorize, :except => [:index]
  before_filter :find_optional_project, :only => [:index]
  before_filter :check_for_default_issue_status, :only => [:new, :create]
  before_filter :build_new_issue_from_params, :only => [:new, :create, :update_form]
  accept_rss_auth :index, :show
  accept_api_auth :index, :show, :create, :update, :destroy
  rescue_from Query::StatementInvalid, :with => :query_statement_invalid
  def bulk_update
    @copy = params[:copy].present?
    attributes = parse_params_for_bulk_issue_attributes(params)
    unsaved_issues = []
    saved_issues = []
    if @copy && params[:copy_subtasks].present?
      # Descendant issues will be copied with the parent task
      # Don't copy them twice
      @issues.reject! {|issue| @issues.detect {|other| issue.is_descendant_of?(other)}}
    @issues.each do |orig_issue|
      if @copy
        issue = orig_issue.copy({},
          :attachments => params[:copy_attachments].present?,
          :subtasks => params[:copy_subtasks].present?
        issue = orig_issue
      journal = issue.init_journal(User.current, params[:notes])
      issue.safe_attributes = attributes
      call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
      if issue.save
        saved_issues << issue
        unsaved_issues << orig_issue
    if unsaved_issues.empty?
      flash[:notice] = l(:notice_successful_update) unless saved_issues.empty?
      if params[:follow]
        if @issues.size == 1 && saved_issues.size == 1
          redirect_to issue_path(saved_issues.first)
        elsif saved_issues.map(&:project).uniq.size == 1
          redirect_to project_issues_path(saved_issues.map(&:project).first)
        redirect_back_or_default _project_issues_path(@project)
      @saved_issues = @issues
      @unsaved_issues = unsaved_issues
      @issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).all
      render :action => 'bulk_edit'

Download a sample

Sample chapter is describing refactoring technique called "render view with locals". It is a great technique to make explicit what data must be provided for the view for it to be working correctly. In few years old Rails applications it is common that controllers set up a lot of instance variables and some of the views depend on them and some do not. Over time it's becoming harder and harder to maintain and refactor views and controllers.

Explicitness here makes it easier to find out common usages and where things differ. It makes refactoring easier for both parts. When you know in your controllers which instance variables are not used by the view you can more easily extract them to methods, local variables or even remove completely if they are no longer needed.

Refactoring view templates and partials also becomes easier because you know what must be provided for them to work. So you can more easily reuse already existing code in other parts of the applications. There are no longer hidden dependencies such as instance variables set up by before-filter from parent controller.


Adam Piotrowski

CTO at 2N

“In our company each developer who achieved basic knowledge about rails way and all of it benefits and disatvantages gets a really important ticket - read Fearless Refactoring asap.

This book helps us refactor old legacy code that is a lot more complicated that it should be for given feature. All solutions included there give us knowledge how to resolve complex problems by writing clear and well-organized code using the best OOP rules.”


Here's the complete chapter list. Don't miss out on this awesome content.

What is the problem with Rails controllers?

Why service objects?

What is a Rails service object?

Refactoring and the human factor

Inline controller filters

Explicitly render views with locals

Extract render/redirect methods

Extract a Single Action Controller class

Extract routing constraint

Extract an adapter object

Extract a repository object

Extract a service object using the SimpleDelegator

Example: TripReservationsController#create

Example: logging time

Instantiating service objects

Wrap external API with an adapter

What are the supported formats?

Right now we are supporting PDF, .ePub and Amazon Kindle (.Mobi) format. In our opinion it is most convinient to read the book as PDF. You will receive all three formats in a nicely packed ZIP file. What else could you want ???? ?


What if I don't like this book?

If the product doesn't satisfy you, just reply to your purchase receipt email and I will issue a refund. No hard feelings. However only 0,5% customers asked for refund so far.

How am I gonna get the updates?

The book is finished but we occasionally add some new, useful bonus chapters. We will send them to you via email to the same address that you provide during checkout process.

More than 1000 copies already sold

In Fearless Refactoring: Rails controllers I'll teach how to improve your Rails controllers in a quick and safe way. This is step-by-step guide so you won't feel lost. Every step is described in every detail, with code changes. All of that, so that you can safely refactor your codebase, even without a full test coverage.

Over a thousand readers already trusted our expertise.