DEV Community

Alex Aslam
Alex Aslam

Posted on

The "Rails Way" vs. "The Right Way": A Painter's Journey Beyond the Canvas

For years, I thought mastery was found within the lines. I was an apprentice, handed a set of brushes known as Ruby on Rails. Its philosophy, "The Rails Way," was my sacred text. Convention over Configuration. Don't Repeat Yourself. It was a beautiful, pre-stretched canvas, with the initial sketch already laid out.

My early paintings were joyous. A few strokes of a generator command, and a fully functional blog would appear, as if by magic. rails g scaffold Post title:string body:text. It felt like cheating. The framework was my master, and I was its faithful scribe, learning the elegant dance of Models, Views, and Controllers.

This was the Apprentice Phase. I revered the dogma. Fat models, skinny controllers? A commandment. The Asset Pipeline? The one true path. To question it was heresy. My art was clean, consistent, and… derivative.

The First Crack in the Canvas: The Monolith's Groan

Then, the projects grew. The elegant Post model became a monstrous UserAccountManagementService concern. The controller, once skinny, was now obese, juggling JSON APIs, HTML responses, and complex side effects. My app/models directory looked less like a gallery of elegant sculptures and more like a crowded warehouse.

The "Rails Way" started to feel less like a guiding principle and more like a straightjacket. I was forcing complexity into a structure designed for simplicity. Active Record, once a faithful companion, now felt like an ORM that knew too much, tightly coupling my business logic to my database schema.

This was the Journeyman's Crisis. I saw the cracks. The dogma was not sufficient for the problems I now faced. I began to whisper the blasphemous question: "What if there's another way?"

Stepping Outside the Atelier: Discovering the Wider World of Art

I started looking at other artists—architects working in Java, functional programmers in Elixir, and JavaScript engineers building intricate front-end architectures. I discovered concepts that were alien to the "Rails Way":

  • Domain-Driven Design (DDD): Structuring your application around your business domain, not your database tables.
  • Hexagonal Architecture (Ports & Adapters): Making your core logic ignorant of Rails, treating the framework as a plugin.
  • Command-Query Responsibility Segregation (CQRS): Separating the model for writing from the model for reading.
  • Explicit Contracts over Magic: Using dependency injection and plain old Ruby objects (POROs) to make dependencies clear, rather than hiding them in ActiveSupport::Concern.

This wasn't about abandoning Rails. It was about redefining its role. Instead of being the entire studio, Rails could become a powerful, specialized tool within the studio—the excellent easel that holds the canvas, but not the hand that paints.

The Master's Realization: The "Right Way" is Contextual

The "Right Way" is not a destination you find on a map. It's the judgment you develop after a long journey. It’s the wisdom to know when to use the "Rails Way" and when to transcend it.

Let's translate this into code. Imagine a UserRegistration flow.

The "Rails Way" (in a controller):

# app/controllers/users_controller.rb
def create
  @user = User.new(user_params)
  if @user.save
    UserMailer.welcome_email(@user).deliver_later
    session[:user_id] = @user.id
    redirect_to dashboard_path, notice: 'User was successfully created.'
  else
    render :new
  end
end
Enter fullscreen mode Exit fullscreen mode

This is simple, elegant, and perfect for a small application. But the business logic is trapped in the controller, tied to HTTP and the session.

A "Right Way" for a complex domain (using a Service Object):

# app/services/user_registration.rb
class UserRegistration
  def initialize(user_params, mailer: UserMailer, session: SessionManager.new)
    @user_params = user_params
    @mailer = mailer
    @session = session
  end

  def call
    user = build_user
    return Failure(user.errors) unless user.valid?

    # A transaction boundary for the operation
    ActiveRecord::Base.transaction do
      user.save!
      @mailer.welcome_email(user).deliver_later
      @session.login(user)
      # Perhaps other side effects: create a profile, add to a mailing list, etc.
    end

    Success(user)
  rescue => e
    Failure(e.message)
  end

  private

  def build_user
    User.new(@user_params).tap do |u|
      u.role = :member # Complex domain logic
      u.onboarding_status = :pending
    end
  end
end

# The controller becomes a thin integration layer
def create
  result = UserRegistration.new(user_params, session: session).call

  if result.success?
    redirect_to dashboard_path, notice: 'Welcome!'
  else
    @user = result.failure
    render :new
  end
end
Enter fullscreen mode Exit fullscreen mode

This second approach is more code, yes. But it's also more resilient, testable, and explicit. The core concept of "registering a user" is a first-class citizen in your codebase, not a side effect of a controller action. You can test UserRegistration in isolation, without the HTTP layer. You've begun to paint your business logic onto a separate layer, independent of the Rails canvas.

The Artwork: A Balanced Palette

So, is the "Rails Way" wrong? Absolutely not. It's a masterpiece of productivity for a certain class of problems.

The true artistry for a senior developer lies in intentional architecture.

  • Use the "Rails Way" for what it's brilliant at: Rapid prototyping, CRUD-heavy admin sections, and leveraging the vast ecosystem of gems.
  • Transcend it when necessary: When your core domain logic becomes complex, abstract it into POROs, service objects, or event-driven systems. Use Rails to handle the delivery mechanism (HTTP), the database connection, and the background jobs, but not as the container for all your business rules.

Your application is your ultimate artwork. The "Rails Way" provides the finest quality paints and brushes. But you, the senior developer, are the artist. You must know when to follow the classical techniques and when to break the rules to create something truly original, maintainable, and robust.

Don't be a slave to dogma. Be its master. Your journey is not about finding the one "Right Way," but about developing the wisdom to choose the right path for the problem at hand. Now, go paint your masterpiece.

Top comments (0)