DEV Community

Germán Alberto Gimenez Silva
Germán Alberto Gimenez Silva

Posted on • Originally published at rubystacknews.com on

🧼 Skinny Controllers, Fat Models – A Classic Ruby on Rails Guideline

June 5, 2025

In the world of Ruby on Rails , few principles have stood the test of time like the mantra: “Skinny Controllers, Fat Models.” While it may sound quirky, this simple phrase encapsulates a deep architectural philosophy that encourages maintainability, clarity, and clean code — the Rails way.

âś… What It Really Means

The idea is straightforward:

  • Controllers should be lean. Their job is to handle HTTP requests, delegate business logic, and render responses. Think of them as the traffic coordinators of your application — directing flow, but not doing the heavy lifting.
  • Models should carry the weight of your application’s business logic. They encapsulate rules, behaviors, and interactions with the database.

This separation leads to better-structured, more maintainable applications. Your logic lives closer to your data, where it often belongs.


📬 Let’s Connect!

If you’re passionate about clean architecture, Ruby on Rails, or just want to chat about code, feel free to connect or reach out. I’m always open to sharing ideas, exploring collaborations, or learning something new.

💬🔗


đź§© Why It Matters

Let’s face it — Rails apps can get messy if you’re not careful. When too much logic creeps into controllers, you end up with code that’s hard to test, harder to reuse, and nearly impossible to maintain as your app scales.

By keeping controllers “skinny,” you ensure that:

  • Your app follows the Single Responsibility Principle
  • You can test business rules independently of HTTP interactions
  • Reusability becomes easier (e.g., business logic in models or service objects can be reused in background jobs, rake tasks, APIs, etc.)

🔨 Practical Example

Bad example — Fat controller :


class OrdersController < ApplicationController
  def create
    order = Order.new(order_params)
    if order.total > current_user.credit_limit
      flash[:alert] = "Insufficient credit"
      render :new
    else
      order.user = current_user
      order.save
      UserMailer.order_confirmation(order).deliver_later
      redirect_to order_path(order)
    end
  end
end

Enter fullscreen mode Exit fullscreen mode

Better — Skinny controller, fat model (or service):


class OrdersController < ApplicationController
  def create
    result = OrderProcessor.new(current_user, order_params).call

    if result.success?
      redirect_to result.order, notice: "Order placed successfully!"
    else
      flash[:alert] = result.error
      render :new
    end
  end
end

Enter fullscreen mode Exit fullscreen mode

Here, OrderProcessor encapsulates the order logic — keeping our controller clean and focused.


🔍 When “Fat” Models Become Too Fat

Article content

Let’s not ignore the elephant in the room. While this principle is a great starting point, sometimes the model ends up doing too much. When that happens, consider extracting concerns into:

  • Service objects
  • Form objects
  • Value objects
  • Interactors or use-cases

The key is balance — aim for modularity and readability, not just blindly following the mantra.


🚀 Conclusion

“Skinny Controllers, Fat Models” is more than a Rails cliché. It’s a guidepost toward writing clearer, cleaner, and more scalable code. By giving your controllers the job of coordination and your models the job of encapsulating logic, you’re embracing a pattern that’s helped Rails developers for years — and will likely keep doing so for many more.

What’s your take on this principle in 2025? Have you evolved it with services or taken a different path? I’d love to hear how others are approaching Rails architecture today!

Article content

Top comments (0)