Search code examples
ruby-on-railslayoutdynamic-programmingrails7

More than 2 dynamic layout options per controller in Rails


Using multiple layout statements in Rails will throw an error. Rails ignores all but the last layout statement.

However, I have a complicated layout system where I need to dynamically render several different layouts other than the standard application layout (the layout option in a controller allows for just one alternative layout, the rest defaulting to app/layouts/application.html.erb). I was hoping the following would be a good substitute:

In this case, I'm using a static_controller.rb to render the following static content pages (about.html.erb, contact.html.erb, careers.html.erb, help.html.erb, home.html.erb, landing.html.erb, legal.html.erb, and policies.html.erb).

  1. landing.html.erb will have a custom, full-page layout with no header or footer.
  2. about, contact, home, and legal will each follow the "main" layout [app/views/layouts/main.html.erb].
  3. careers, help, and policies will each follow the "not_main" layout [app/views/layouts/not_main.html.erb].

I need something similar to this in the target controller:

class StaticController < ApplicationController
...
layout 'full', :only => [:landing]

%w[about contact home legal ].each do |static_page|
  layout 'main'
end

%w[careers help policies].each do |static_page|
  layout 'not_main'
end
...
def about
end
...
end #Closes the Static Controller

This would be preferable to setting the layout in each action call. However, Rails continues to ignore the previous layout statements, even though they are wrapped in a %w array. Any ideas how to make something like this work?


Solution

  • This works for me on Rails7:

    class StaticController < ApplicationController
    
      layout :select_layout
    
    private
      def select_layout
        "main" if %w[about contact home legal].include? action_name
        "full" if %w[landing].include? action_name
        # ...etc
      end
    
    end