TIL: Rails has a magical layout management feature

AI taught me how to make the app html file of my SaaS app manageable using layouts

i'm working on a massive redesign project on my SaaS app to make it "drop dead gorgeous". first part is dealing with my monster 200+ line application.html.erb file that handles all the complex header/footer styles.

so i show this file to the ai and here's the conversation that followed:


ai: Oh my! I can see exactly what we're dealing with here. The current application.html.erb is quite... let's say "organically grown" 😄 with lots of inline conditions and a complex navigation structure. But don't worry - this is a common situation in growing applications, and we'll clean it up nicely!

I notice several areas we can improve:

  • The header/navigation logic is quite complex with many conditional checks
  • Lots of inline classes that could be componentized
  • Complex mobile menu implementation
  • Multiple footer variations that could be unified
  • Complex link structure that could be organized better

Before we dive into the rebuild, it would be helpful to see

  • any existing view components you've created (especially navigation-related ones).
  • Your current routes.rb file to understand the navigation structure better

Me: i'll give you those files but what i think would be best is to keep the app html file clean and minimal. because with the current one, it was annoying to get a fixed header and footer and background color on every page. even the margins on left/right.

i think it might be best to have this layout file not handle any of this stuff.

what do you think? am i thinking about it right?


ai: Absolutely, you're thinking about this exactly right! 🎯 This is a perfect example of separation of concerns and following the "Single Responsibility Principle."

  1. Make application.html.erb Minimal:
  • Keep only essential meta tags, assets, and basic structure
  • No styling or complex layout logic
  • Just a clean container for other layouts to build upon

2. Create Multiple Layout Files:

  • layouts/public.html.erb - For marketing pages with the fancy footer
  • layouts/app.html.erb - For authenticated dashboard views
  • layouts/minimal.html.erb - For sign-up flows and simple pages

3. Extract Components:

  • shared/_header.html.erb - Navigation component
  • shared/_footer.html.erb - Footer component
  • shared/_flash.html.erb - Flash messages

Here's what a clean application.html.erb might look like:

<!DOCTYPE html>
<html lang="<%= I18n.locale %>">
  <head>
    <title><%= content_for?(:title) ? yield(:title) : "Curated Connections" %></title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= display_meta_tags %>
    <%= favicon_link_tag 'favicon.ico' %>

    <%= stylesheet_link_tag "tailwind", "inter-font", "data-turbo-track": "reload" %>
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_importmap_tags %>

    <%= yield :head %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

Then in your controllers, you can specify which layout to use:

class PagesController < ApplicationController
  layout 'public'
  # ...
end

class DashboardController < ApplicationController
  layout 'app'
  # ...
end

Me: yes i really like this approach. can you tell me more about that specifying the layout in the controller thing that you did. that looks awesome and i didn't know rails supported something like this.

how does it work? and is it something people often do?


ai: Ah yes! Layout management in Rails is a super powerful feature that's commonly used in professional Rails apps. It's one of those "Rails magic" features that makes complex layout management really elegant! 😄

Here's the complete breakdown:

  1. Basic Layout Specification
class DashboardController < ApplicationController
  layout 'app'  # This will use layouts/app.html.erb
end

2. Dynamic Layouts - You can even make it conditional:

class CommunitiesController < ApplicationController
  # Method that returns a layout name
  layout :determine_layout

  private

  def determine_layout
    if action_name == 'show' && current_user.admin?
      'admin'
    else
      'app'
    end
  end
end

3. Per-Action Layout Override

class PagesController < ApplicationController
  layout 'public'

  # Override for specific action
  def pricing
    render layout: 'minimal'
  end
end

4. Layout Inheritance - Layouts cascade through your controller hierarchy:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  layout 'application'  # Default layout for all controllers
end

# app/controllers/admin/base_controller.rb
class Admin::BaseController < ApplicationController
  layout 'admin'  # All admin controllers will use this layout
end

# app/controllers/admin/users_controller.rb
class Admin::UsersController < Admin::BaseController
  # Automatically uses admin layout from parent
end

5. Skip Layout Entirely

class ApiController < ApplicationController
  layout false  # No layout will be used
end

This approach:

  • Keeps your layouts organized and purpose-specific
  • Makes it easy to change layouts for entire sections of your app
  • Follows the DRY principle
  • Is very maintainable as your app grows