Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #3647 (new defect)

Opened 2 years ago

Last modified 1 year ago

layout inheritance broken with :only

Reported by: csn Assigned to: David
Priority: high Milestone:
Component: ActionPack Version: edge
Severity: major Keywords:
Cc: justin@aspect.net, japgolly@gmail.com

Description

If I have in application_controller.rb:

layout 'standard'

and in some_controller.rb

layout 'special', :only=>[:a, :b, :c]

All other actions in some_controller will use NO template at all, rather than using the 'standard' layout specified in application.rb. Actions not in :only, or in :except should inherit application.rb's layout IMO.

Attachments

foobar.zip (68.9 kB) - added by vocaro on 07/16/07 17:41:49.
Test case showing bug in handling of layout :only with layout :except

Change History

02/12/06 06:53:03 changed by anonymous

  • component changed from ActiveRecord to ActionPack.

07/23/06 17:40:44 changed by gabe@websaviour.com

  • version changed from 1.0.0 to 1.1.1.

This bug still exists in 1.1.4 and occurs even for layouts specified in the same file. I discovered it when I had no explicit layouts (just using "application" implicitly) and I added the following for the splash page of the site:

layout nil, :only => :index

Which resulted in all of that controller's actions using no layout.

A workaround attempt failed:

layout nil, :only => :index
layout "application"

However if I made the layout specification explicit (using :only, not :except) in a second declaration after the first one then it works:

layout nil, :only => :index
layout "application", :only => [:school, :salon, :contact]

I would love to get inside Rails and create a patch for this, but I'm on a time constraint. I think this is big enough that it should be fixed for the next version. I also expect it's a pretty easy fix.

07/31/06 14:53:41 changed by anonymous

  • cc set to justin@aspect.net.

09/27/06 03:21:55 changed by japgolly

  • cc changed from justin@aspect.net to justin@aspect.net, japgolly@gmail.com.
  • priority changed from normal to high.
  • version changed from 1.1.1 to 1.1.6.
  • severity changed from normal to major.
  • milestone set to 1.2.

Same problem still exists in 1.1.6. This is a serious problem so I'm up'ing the priority.

(in reply to: ↑ description ) 01/26/07 14:47:24 changed by DerGuteMoritz

  • version changed from 1.1.6 to 1.2.0.
  • milestone deleted.

Still exists in 1.2!

04/04/07 23:35:30 changed by timocratic

  • version changed from 1.2.0 to edge.

It seems to be in this block ActionController::Layout line 293

      def action_has_layout?
        if conditions = self.class.layout_conditions
          case
            when only = conditions[:only]
              only.include?(action_name)
            when except = conditions[:except]
              !except.include?(action_name) 
            else
              true
          end
        else
          true
        end
      end

Basically, if an only exists, and this action isn't in it, set action_has_layout? to false. I tested that this is where the bug is by returned true, but haven't created tests or a patch.

04/04/07 23:53:31 changed by timocratic

Of course - it's a quite a bit more complicated than that, but that's the most obvious entry point to the bug.

07/16/07 17:41:49 changed by vocaro

  • attachment foobar.zip added.

Test case showing bug in handling of layout :only with layout :except

07/16/07 17:42:01 changed by vocaro

I ran into a very similar problem, except I wasn't even using inheritance. There seems to be a bug in the handling of :only and :except layouts. For example, if you have a controller Foo, and you want action "a" to use layout "foo", and action "b" to use layout "bar", then you might add something like this to Foo:

  layout "foo", :only => :a
  layout "bar", :except => :a

But this does not work as expected. Action "a" gets layout "bar", and action "b" gets no layout at all!

I've attached a test case showing the problem on Rails 1.2.3. To reproduce, start the server and go to http://localhost:3000/foo/a and http://localhost:3000/foo/b

07/16/07 18:35:40 changed by vocaro

Actually, the issue I just reported seems to be a duplicate of #8867.