0

In one of my controllers I want to change the layout given some condition, and otherwise keep the default layout used by the parent ApplicationController (was "application" initially, but I'm trying some others now). Tried accessing the "layout" using alias_method but it doesn't seem to work. My code:

class SomeController < ApplicationController
  alias_method :parent_layout, :layout
  layout :some_layout

  def some_layout
    if some_condition
      "new_layout"
    else
      :parent_layout
    end
  end
end

This gives an error:

ActionController::RoutingError (undefined method `layout' for class `SomeController'):
  app/controllers/some_controller.rb:6:in `alias_method'
  app/controllers/some_controller.rb:6:in `<class:SomeController>'
  app/controllers/some_controller.rb:3:in `<top (required)>'
shaimo
  • 376
  • 3
  • 17

1 Answers1

0

It looks like you have a bunch of options. Check out the docs here (search for "finding layouts") http://guides.rubyonrails.org/layouts_and_rendering.html

Some possibilities, depending on just how complex you need it to be:

# Proc-based
class ProductsController < ApplicationController
  layout Proc.new { |controller| controller.request.xhr? ? "popup" : "application" }
end

# Route based, :except and :only
class ProductsController < ApplicationController
  layout "product", except: [:index, :rss]
end

# Method-based
class OldArticlesController < SpecialArticlesController
  layout false

  def show
    @article = Article.find(params[:id])
  end

  def index
    @old_articles = Article.older
    render layout: "old"
  end
  # ...
end

I'm not sure how your code is structured but it looks like the first could work for you:

class SomeController < ApplicationController
  layout Proc.new { |controller| controller.some_condition? ? "new_layout" : "application" }
end
alexcavalli
  • 526
  • 6
  • 10
  • Thanks @alexcavalli. Not sure this solves my issue. The first option you suggested provides the explicit layout file for each case of the condition. What I want to do is provide it only under some condition, and otherwise use the one from the base class. It could be "application" or it could be something else that was indicated in the "layout" method (or variable) of ApplicationController. I don't want to duplicate it here. How can I replace "application" above with the layout from the base ApplicationController (that can have its own conditions, etc I guess)? – shaimo Feb 28 '15 at 23:18
  • @shaimo I see. In that case, perhaps the last one will work? It seems like (I haven't tested it) it would use the parent layout unless you set an explicit layout in the `render` call. Although it might result in quite a bit of clutter if you have to insert the `render layout: "new_layout"` in many methods. – alexcavalli Feb 28 '15 at 23:21