Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Conditional layouts ignore default application wide layout

#3619

Suppose you have a layout called "application.html.erb", your main application layout. Now if you have a controller with 7 actions but want to apply a different layout in one action, like:

layout "full_width", :only => :index

the other six actions won't use any layout at all. The same occurs with the :except option.

I think the current behavior is neither intuitive nor desirable in most cases. IMHO It would make more sense to default the unmatched actions to the application.html.erb layout.

Reported by Henrique · December 26th, 2009 @ 10:50 PM

State: stale
Milestone: 2.3.10
Assigned to: Jeremy Kemper Jeremy Kemper
Importance: Medium

Activity

  1. Daniel Guettler
    Daniel Guettler

    I think the reason for this would be that the "_action_has_layout?" method returns false if you use the "layout" method to set the layout with conditions and the action called is not in the list.
    As a workaround I would pass the layout to render in the index action like so:

    {{{ def index

    # ...
    render :layout => 'full_width'
    

    end }}}

    this way the index action will render full_width and all other actions will default to the application layout or whatever other layout you have specified.

    December 28th, 2009 @ 08:43 PM

  2. Dmitry Polushkin
    Dmitry Polushkin
    • Tag changed from layout to conditions, layout

    Tried to do:

    layout nil, :only => [:create, :destroy]
    

    And it also applied for index action. Except does the same.

    Workaround:

    render :layout => false
    

    In every action.

    January 11th, 2010 @ 06:40 PM

  3. Dmitry Polushkin
    Dmitry Polushkin
    • Tag changed from conditions, layout to nested layouts, conditions, layout
    • Assigned user set to José Valim

    March 12th, 2010 @ 03:55 PM

  4. José Valim
  5. Dmitry Polushkin
    Dmitry Polushkin
    • Tag changed from nested layouts, conditions, layout to nested layouts, 2.3.5, conditions, layout

    2.3.5

    March 12th, 2010 @ 04:31 PM

  6. José Valim
    José Valim
    • Assigned user cleared.

    Could you please provide a failing test case or even a patch?

    March 12th, 2010 @ 04:32 PM

  7. Dmitry Polushkin
    Dmitry Polushkin

    OK, I will try to do it tomorrow.

    March 12th, 2010 @ 04:35 PM

  8. Dmitry Polushkin
    Dmitry Polushkin
    • Tag changed from nested layouts, 2.3.5, conditions, layout to nested layouts, 2.3.5, 2.x, conditions, layout

    Added 2 failed tests for nested/inherited layout with condition and just simple layout with condition.

    March 13th, 2010 @ 11:04 PM

  9. Dmitry Polushkin
    Dmitry Polushkin
    • Assigned user set to Jeremy Kemper

    March 18th, 2010 @ 03:56 PM

  10. Jeremy Kemper
    Jeremy Kemper
    • Milestone set to 2.3.6
    • State changed from new to open

    Thanks for the tests, Dmitry. Good case to cover.

    Does it work on master? Patches welcome :)

    March 18th, 2010 @ 05:55 PM

  11. Fernando Guillen
    Fernando Guillen

    I have been looking at this problem and my conclusion is that the problem in here is that one controller only can stores one layout definition:

    # layout.rb
    
    def layout(template_name, conditions = {}, auto = false)
      add_layout_conditions(conditions)
      write_inheritable_attribute(:layout, template_name)
      write_inheritable_attribute(:auto_layout, auto)
    end
    

    So each time we call to layout method the layout attribute will be reset to the new value even if this layout is intended to be used only on one action.

    Another problem in here is that we can't make a definition like this:

    class HasTwoOwnLayoutWithConditionsController < LayoutTest
      layout 'layout_wadus', :only => 'wadus'
      layout 'layout_churro', :only => 'churro'
    end
    

    Because the second call to layout method will delete what is defined on the first one, so this is not gonna work:

    def test_layout_with_two_layouts_with_conditions_definided
      @controller = HasTwoOwnLayoutWithConditionsController.new
      get :churro
      assert_equal 'layouts/layout_churro', @response.layout
      
      get :wadus
      assert_equal 'layouts/layout_wadus', @response.layout
      
      get :hello
      assert_equal 'layouts/layout_test', @response.layout
    end
    

    If we add to the fixtures/layout_tests all the layouts and views needed only the first assertion will work because it is defined on the last call to the layout method.

    What I think could be a solution is to change the layout.rb class so on every call to layout method a new layout definition will be stored but without delete the already stored layouts, so what we will have will be an Stack of layouts and to figure out what layout has to be used on a particular action of a particular controller we will have to check all the Stack from top to bottom.

    The problem is double because the layout definition is not stored on only one attribute, remember the method layout on the class layout.rb pasted above.

    I can try to implement a solution but I need to receive feedback of my conclusions since this could be a very big change on layout implementation.

    Regards.

    f.

    March 26th, 2010 @ 10:41 AM

  12. Neeraj
    Neeraj

    Fernando has a good point. Maintaing the stack seems like a good idea. However if the stack has options like only and except then figuring out the correct layout might take time and there will be performance hit.

    The other approach would be to resolve which layout will be applied to which method at boot time. The issue in this case would be if someone adds a new method to a controller dynamically.

    I haven't looked at rails3 but I do remember that in one of the speeches Yehuda mentioned that to make filters run faster in rails3 , he takes that second approach mentioned above. I might be wrong but he resolves what all filters will be applied to a method at boot time. Not sure how and if he handles if a method is added dynamically.

    Either way the solution would require some structural change. And as Fernando said a high level guideline from the core team would be a help.

    April 16th, 2010 @ 04:39 PM

  13. Federico Brubacher
    Federico Brubacher

    Hey guys, I made other ticket with a more limited scope, but I agree with Fernando we should have more flexibility and even ability to add 2+ layout declarations.

    https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets...

    May 8th, 2010 @ 09:39 PM

  14. Rizwan Reza
    Rizwan Reza
    • Tag changed from nested layouts, 2.3.5, 2.x, conditions, layout to nested layouts, 2.3.5, 2.x, bugmash, conditions, layout

    May 16th, 2010 @ 02:41 AM

  15. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.3.6 to 2.3.7

    May 23rd, 2010 @ 05:54 PM

  16. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.3.7 to 2.3.8

    May 24th, 2010 @ 09:40 AM

  17. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.3.8 to 2.3.9

    May 25th, 2010 @ 11:45 PM

  18. Jeremy Kemper
    Jeremy Kemper
    • Milestone changed from 2.3.9 to 2.3.10
    • Importance changed from to Medium

    August 30th, 2010 @ 02:28 AM

  19. Santiago Pastorino
    Santiago Pastorino
    • Tag changed from nested layouts, 2.3.5, 2.x, bugmash, conditions, layout to nested layouts, 235, 2x, bugmash, conditions, layout

    This issue has been automatically marked as stale because it has not been commented on for at least three months.

    The resources of the Rails core team are limited, and so we are asking for your help. If you can still reproduce this error on the 3-0-stable branch or on master, please reply with all of the information you have about it and add "[state:open]" to your comment. This will reopen the ticket for review. Likewise, if you feel that this is a very important feature for Rails to include, please reply with your explanation so we can consider it.

    Thank you for all your contributions, and we hope you will understand this step to focus our efforts where they are most helpful.

    February 2nd, 2011 @ 04:49 PM

  20. Santiago Pastorino
    Santiago Pastorino
    • State changed from open to stale

    February 2nd, 2011 @ 04:49 PM