This project is archived and is in readonly mode.

#3619 ✓stale
Henrique

Conditional layouts ignore default application wide layout

Reported by Henrique | December 26th, 2009 @ 10:50 PM | in 2.3.10

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.

Comments and changes to this ticket

  • Daniel Guettler

    Daniel Guettler December 28th, 2009 @ 08:43 PM

    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.

  • Dmitry Polushkin

    Dmitry Polushkin January 11th, 2010 @ 06:40 PM

    • 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.

  • Dmitry Polushkin

    Dmitry Polushkin March 12th, 2010 @ 03:55 PM

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

    Dmitry Polushkin March 12th, 2010 @ 04:31 PM

    • Tag changed from nested layouts, conditions, layout to nested layouts, 2.3.5, conditions, layout

    2.3.5

  • José Valim

    José Valim March 12th, 2010 @ 04:32 PM

    • Assigned user cleared.

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

  • Dmitry Polushkin

    Dmitry Polushkin March 12th, 2010 @ 04:35 PM

    OK, I will try to do it tomorrow.

  • Dmitry Polushkin

    Dmitry Polushkin March 13th, 2010 @ 11:04 PM

    • 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.

  • Dmitry Polushkin

    Dmitry Polushkin March 18th, 2010 @ 03:56 PM

    • Assigned user set to “Jeremy Kemper”
  • Jeremy Kemper

    Jeremy Kemper March 18th, 2010 @ 05:55 PM

    • 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 :)

  • Fernando Guillen

    Fernando Guillen March 26th, 2010 @ 10:41 AM

    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.

  • Neeraj

    Neeraj April 16th, 2010 @ 04:39 PM

    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.

  • Federico Brubacher

    Federico Brubacher May 8th, 2010 @ 09:39 PM

    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...

  • Rizwan Reza

    Rizwan Reza May 16th, 2010 @ 02:41 AM

    • Tag changed from nested layouts, 2.3.5, 2.x, conditions, layout to nested layouts, 2.3.5, 2.x, bugmash, conditions, layout
  • Jeremy Kemper

    Jeremy Kemper May 23rd, 2010 @ 05:54 PM

    • Milestone changed from 2.3.6 to 2.3.7
  • Jeremy Kemper

    Jeremy Kemper May 24th, 2010 @ 09:40 AM

    • Milestone changed from 2.3.7 to 2.3.8
  • Jeremy Kemper

    Jeremy Kemper May 25th, 2010 @ 11:45 PM

    • Milestone changed from 2.3.8 to 2.3.9
  • Jeremy Kemper

    Jeremy Kemper August 30th, 2010 @ 02:28 AM

    • Milestone changed from 2.3.9 to 2.3.10
    • Importance changed from “” to “Medium”
  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:49 PM

    • 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.

  • Santiago Pastorino

    Santiago Pastorino February 2nd, 2011 @ 04:49 PM

    • State changed from “open” to “stale”

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Shared Ticket Bins

Attachments

Referenced by

Pages