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 (
nixinstead ofreject) - Unused response data cluttering JSON renders
The Approach
Rather than a big-bang rewrite, we tackled one concern at a time:
- Extract filter options to a presenter
- Move edit tracking to a dedicated service
- Extract field configuration to model + resolver
- 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 memoizationJobListingEditService— Edit tracking with audit recordsInlineEditableconcern +InlineFieldResolver— Convention-based field configInlineEditableControllerconcern — 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.