52

I could not find any docs or examples on how to structure my app to allow different views in the same controller to use completely different layouts and stylesheets.

Our app was scaffolded and we then used nifty-generators to generate views, then added devise for authentication. We have views and controllers for two models: widgets and companies.

I currently have a single layout: layouts/application.html.haml, I don't see that referenced anywhere so I assume (a rails newbie) that it's always used by naming convention.

I now need to add a couple of views (for mobile browsers) which have a different stylesheet and layout (for example, no login/logout links in the top right), within the same controllers.

How can that be done?

jpw
  • 18,697
  • 25
  • 111
  • 187

5 Answers5

129

By default, layouts/application.html.haml (.erb if you are not using haml).

In fact, layout file could be set per controller or per action, instead of per view, per view folder.

There are few cases:

To change the default layout file for all controller (ie. use another.html.haml instead of application.html.haml)

class ApplicationController < ActionController::Base
  layout "another"

  # another way
  layout :another_by_method
  private
  def another_by_method
    if current_user.nil?
      "normal_layout"
    else
      "member_layout"
    end
  end
end

To change all actions in a certain controller to use another layout file

class SessionsController < ActionController::Base
  layout "sessions_layout"
  # similar to the case in application controller, you could assign a method instead
end

To change an action to use other layout file

def my_action
  if current_user.nil?
    render :layout => "normal_layout"
  else
    render :action => "could_like_this", :layout => "member_layout"
  end
end
PeterWong
  • 15,951
  • 9
  • 59
  • 68
  • 1
    I like your member layout helper, I never thought of doing that! – dannymcc Feb 23 '11 at 11:28
  • 3
    With the last approach for actions I was having issues with the layout rendering properly. I added this to the top of the controller `layout "cust_layout", :only => [:my_action]` to fix the issue. I also dropped the `render :layout => "normal_layout"` in the action and replaced it with `format.html`. Reference this link for conditional layouts -- [Rails Conditional Layouts](http://guides.heroku.com/2.3.5/layouts_and_rendering.html#conditional-layouts) – Stephen Sprinkle Jun 15 '12 at 22:36
4

If you do not want to go too complex, you can simply do this:

layout 'layout_one'

 def new
   @user= User.new
  render layout: 'landing_page'
  end

this will do.

Lesly Revenge
  • 894
  • 10
  • 16
4

I am sure there's plenty of answers to this but here's another one where you can use different layouts per controllers or per action.

class ListingsController < ApplicationController
  # every action will use the layout template app/views/layouts/listing_single.html.erb
  layout 'listing_single'
  # the 'list' action will use the layout set in the 'alternative_layout' method
  # you can also add multiple actions to use a different layout,just do like layout :alternative_layout, only: [:list,:another_action]
  layout :alternative_layout, :only => :list

   def show
   end   

   def list
   end

   private
   def alternative_layout
    if current_user.is_super_admin?
       #if current use is super admin then use the layout found in app/views/layouts/admin.html.erb otherwise use the layout template in app/views/layouts/listing_list.html.erb
      'admin'
    else
      'listing_list'
    end
  end
end
zechtz
  • 442
  • 5
  • 10
4

Yes, you can use different layouts and stylesheets within the same controllers.

The rails guide on layouts is a good place to start. Look at Section 3 - Structuring Layouts

There are several ways to use a different layout but one of the easiest is to simply add a file with the same name as your controller in the layouts/ folder. So if your controller is PostsController then adding a layouts/post.html.haml would cause rails to use that layout. If no such layout is found, and no other layouts are specified, rails will use the default of layouts/application.html.haml

Dty
  • 12,253
  • 6
  • 43
  • 61
1

Well, if it's a different view for mobile devices but all desktop versions are the same then you could use JQtouch.

http://railscasts.com/episodes/199-mobile-devices

# config/initializers/mime_types.rb
Mime::Type.register_alias "text/html", :mobile

# application_controller.rb
before_filter :prepare_for_mobile

private

def mobile_device?
  if session[:mobile_param]
    session[:mobile_param] == "1"
  else
    request.user_agent =~ /Mobile|webOS/
  end
end
helper_method :mobile_device?

def prepare_for_mobile
  session[:mobile_param] = params[:mobile] if params[:mobile]
  request.format = :mobile if mobile_device?
end

The above code is taken from the Railscasts example.

dannymcc
  • 3,744
  • 12
  • 52
  • 85