Epic: From 317 Lines to 166 — A Controller Refactoring Journey

This series documents the complete refactoring of Admin::JobListingsController from 317 lines down to 166 — a 48% reduction — while extracting four reusable patterns.

The Starting Point

The controller had accumulated technical debt common to admin interfaces:

  • Inline filter logic duplicated across actions
  • Edit tracking constants and methods mixed with request handling
  • A 50-line case statement for inline field configuration
  • Colloquial naming (nix instead of reject)
  • Unused response data cluttering JSON renders

The Approach

Rather than a big-bang rewrite, we tackled one concern at a time:

  1. Extract filter options to a presenter
  2. Move edit tracking to a dedicated service
  3. Extract field configuration to model + resolver
  4. Extract the update action to a controller concern

Each step was verified with tests before moving to the next. Each extraction created a reusable pattern.

The Result

Four standalone patterns that work together or independently:

  • JobListingsFilterPresenter — Filter options with memoization
  • JobListingEditService — Edit tracking with audit records
  • InlineEditable concern + InlineFieldResolver — Convention-based field config
  • InlineEditableController concern — Reusable inline edit action

The controller now does what controllers should: receive requests, coordinate services, render responses.

Read the Series

Each article below shows the before/after code and explains the reasoning behind the extraction.

← Back to all articles