Home About me Blog Contact Github Explore
Ruby on Rails

The Most Common Mistakes I See in Rails Applications

After several years working with Ruby on Rails, I've seen countless projects – from freshly started startups to legacy applications that are a decade old. Although Rails provides excellent conventions and tools, I still encounter the same mistakes that make code difficult to maintain and develop. Today I want to discuss the three most common problems I struggle with.

The Most Common Mistakes I See in Rails Applications

Fat models – when models grow infinitely

"Fat models, skinny controllers" – this Rails principle was the community's mantra for years. The problem is that many teams took it too literally and ended up with ActiveRecord models that have hundreds, sometimes over a thousand lines of code.

A classic example: you have a User model and instead of keeping only logic related to persistence, validation, and basic associations, you start adding methods for sending emails, generating reports, calculating statistics, integrating with external APIs, and dozens of other things. As a result, the model becomes a god object that knows and does everything.

The consequences are painful – tests for such a model take forever, every change requires reading hundreds of lines of code, and onboarding new developers feels like hacking through a jungle. Worse still, we violate the Single Responsibility Principle to the extreme.

The solution? Extract business logic into dedicated objects. Service objects, form objects, query objects, presenters – all these patterns help break down a fat model into smaller, single-purpose classes. An ActiveRecord model should primarily be responsible for persistence and basic behaviors related to a given domain entity.

Lack of tests – a time bomb

I've seen Rails projects with practically no tests. "We didn't have time," "it's just an MVP," "we'll add them later" – I know all these excuses. Then comes the moment when something needs to be changed and nobody has any idea what will break.

Lack of tests isn't just a code quality problem. It's a team psychology problem. Without tests, developers are afraid to refactor because they don't have a safety net. The code gets worse and worse because it's easier to add another if statement than to clean up the existing mess. A vicious cycle forms – the worse the quality, the harder it is to add tests, and the fewer tests, the worse the quality.

What particularly hurts me is the lack of integration tests in Rails applications. Unit tests are one thing, but in Rails, it's crucial to have tests that verify whether all elements work together properly – controllers, models, views, mailers. RSpec, Minitest, system tests – there's no shortage of tools, and the benefits are enormous.

You don't need 100% test coverage from day one, but critical paths in the application (registration, login, payments, main business features) should be covered by tests from the very beginning. Treat it as an investment that will pay off many times over.

Poor service structure – chaos in disguise

When a team finally understands that fat models are evil, they often fall into another trap – poorly designed service objects. I've seen applications with an app/services folder full of classes that aren't actually services, but a chaotic mix of different patterns and responsibilities.

Typical problems are services that:

  • Do too much (another god object, only this time in the services folder)
  • Have unclear responsibility (a class called OrderProcessor sounds reasonable, but what exactly does it do?)
  • Are too generic (DataHandler, BusinessLogic – what does that even mean?)
  • Are poorly named (the name doesn't reflect what the class does)
  • Don't have a consistent interface (one service has a call method, another perform, a third execute)

A good service object should have one clearly defined responsibility and a readable name that says what it does. Instead of OrderProcessor, better use Orders::CreateFromCart or Orders::SendConfirmationEmail. The name should be a verb describing an action, not a noun.

Consistency is also important – if you're using a pattern with a call method in your project, stick to it everywhere. If services return result objects, let them all do it. Create conventions and document them so every new team member knows how to create new services.

Summary

Rails is a great framework, but it won't protect you from bad architectural decisions. Fat models, lack of tests, and poorly designed services are problems that destroy projects regardless of the technology used, but I see them especially often in Rails.

The good news is that all these problems can be fixed. It requires discipline, consistency, and sometimes the courage to say "stop, let's refactor before we go further." But trust me – your future self will thank you for it. And so will the team.

Our website uses cookies to enhance your experience. By continuing to browse, you agree to our use of cookies. Read more about it