Forum: Ruby on Rails Another layout question - Layouts on a per method basis - La

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
softwareengineer 99 (Guest)
on 2006-02-05 21:10
(Received via mailing list)
I feel I am very close to understanding how layouts are used in Rails:

  Q1. I know one can specify a "default" layout for all methods in a
controller by specifying
  layout 'my-default-layout'

  How can this be overridden for individual methods so when those
methods  are called/executed, the overridden layout will be used. Is
this  possible?


  Q2. With no "default" layout specified, I tried to use the following
for a method:
      render (:layout =>  'custom-layout-for-method')
  and
      render_component(:action => 'login', :controller=>'member',
:layout=>'custom-layout-for-method')

  but the page is rendered with no layout. Can anyone please explain why
no layout was used? How can I make it use a custom layout on a per
method basis?

 Q3. I am displaying paginated results for the  list action of tags
controller. This page already has a layout defined.  Everything works
fine. Now, I am interested in implementing the  ajax_pagination_links
(http://www.bigbold.com/snippets/posts/show/386).  However since the
layout has already been defined, every time I click  on the page number,
the entire page including the header is loaded  again within my div. I
cannot find how I can turn off the layout  conditionally or alltogether
only for subsequent calls.
  Since my @resource_pages collection  is retrieved in a method that
has a layout defined "globally" how can I turn off the header for
subsequent pages only? I hope I am making sense here.


  Thank you for making me a part of this wonderful community.

  Frank
William H. (Guest)
on 2006-02-06 00:27
Hello Frank,
When you make your layout deceleration in your controller you can pass
:only and :except as parameters.
like this:
layout 'layout_name', :only => [:method1, :method2]

You can also replace the name of the layout with a symbol which
designates a method in the controller to call for determining the
layout.
like this:
layout :determin_layout_method

def determin_layout_method
  if condition == true
    'method1'
  else
    false # returning false will mean no layout is rendered
  end
end

finally you can pass the layout as a parameter in your render call
inside a method but you will need to include a path from template_root
like this:
render :layout => 'layout/template' # notice that is layout/template and
not template

Also remember that layout is just a class method so you can also do
something like this in an instance method:
self.class.layout 'new_layout_for_class' #this is nice because it sets
the layout but you dont need to call render.  This is probably good
practice because you can call the method from other methods in the class
and you wont run into more than one call to render problems.

I hope that helps.

softwareengineer 99 wrote:
> I feel I am very close to understanding how layouts are used in Rails:
>
>   Q1. I know one can specify a "default" layout for all methods in a
> controller by specifying
>   layout 'my-default-layout'
>
>   How can this be overridden for individual methods so when those
> methods  are called/executed, the overridden layout will be used. Is
> this  possible?
>
>
>   Q2. With no "default" layout specified, I tried to use the following
> for a method:
>       render (:layout =>  'custom-layout-for-method')
>   and
>       render_component(:action => 'login', :controller=>'member',
> :layout=>'custom-layout-for-method')
>
>   but the page is rendered with no layout. Can anyone please explain why
> no layout was used? How can I make it use a custom layout on a per
> method basis?
>
>  Q3. I am displaying paginated results for the  list action of tags
> controller. This page already has a layout defined.  Everything works
> fine. Now, I am interested in implementing the  ajax_pagination_links
> (http://www.bigbold.com/snippets/posts/show/386).  However since the
> layout has already been defined, every time I click  on the page number,
> the entire page including the header is loaded  again within my div. I
> cannot find how I can turn off the layout  conditionally or alltogether
> only for subsequent calls.
>   Since my @resource_pages collection  is retrieved in a method that
> has a layout defined "globally" how can I turn off the header for
> subsequent pages only? I hope I am making sense here.
>
>
>   Thank you for making me a part of this wonderful community.
>
>   Frank
softwareengineer 99 (Guest)
on 2006-02-06 01:20
(Received via mailing list)
Hello William,

  Yes, this does help a lot.

  Thank you very much for your time and assistance. It is much
appreciated.

  Frank

william heartwell <removed_email_address@domain.invalid> wrote:I hope that 
helps.
Scott N. (Guest)
on 2006-02-06 01:53
william heartwell wrote:
> finally you can pass the layout as a parameter in your render call
> inside a method but you will need to include a path from template_root
> like this:
> render :layout => 'layout/template' # notice that is layout/template and
> not template
>
> Also remember that layout is just a class method so you can also do
> something like this in an instance method:
> self.class.layout 'new_layout_for_class' #this is nice because it sets
> the layout but you dont need to call render.  This is probably good
> practice because you can call the method from other methods in the class
> and you wont run into more than one call to render problems.

I tried your advice in my account controller but I cant seem to get it
to work.
I tried:
self.class.layout 'frontend'
self.class.layout 'layout/frontend'
self.class.layout 'layouts/frontend'

Here is my code:

class AccountController < ApplicationController
  include AuthenticatedSystem
  before_filter :login_required, :except => [:login]
  layout 'backend', :except => [:login]
...
  def login
    self.class.layout 'frontend' # My public layout is
app/views/layouts/frontend.rhtml
    return unless request.post?
    self.current_user = User.authenticate(params[:login],
params[:password])
    if current_user
      redirect_back_or_default(:controller => '/account', :action =>
'index')
      flash[:notice] = "Logged in successfully"
    else
      flash[:notice] = "Error logging in"
    end
  end
...

What am I doing wrong?
Mikkel B. (Guest)
on 2006-02-06 11:44
(Received via mailing list)
http://api.rubyonrails.org/classes/ActionControlle...


If you have a layout that by default is applied to all the actions of a
controller, you still have the option of rendering a given action or set
of
actions without a layout, or restricting a layout to only a single
action or
a set of actions. The :only and :except options can be passed to the
layout
call. For example:

  class WeblogController < ActionController::Base
    layout "weblog_standard", :except => :rss

    # ...

  end

This will assign "weblog_standard" as the WeblogController's layout
except
for the rss action, which will not wrap a layout around the rendered
view.

Both the :only and :except condition can accept an arbitrary number of
method references, so #:except => [ :rss, :text_only ] is valid, as is
:except
=> :rss.
This topic is locked and can not be replied to.