Rails set layout from within a before_filter method
Is it possible to reset a default layout from within a before_filter method in Rails 3?
I have the following as my contacts_controller.rb:
class ContactsController < ApplicationController
before_filter :admin_required, :only => [:index, :show]
def show
@contact = Contact.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @contact }
end
end
[...]
end
And the following in my application_controller.rb
class ApplicationController < ActionController::Base
layout 'usual_layout'
private
def admin_required
if !authorized? # please, ignore it. this is not important
redirect_to[...]
return false
else
layout 'admin' [???] # this is where I would like to define a new layout
return true
end
end
end
I know I could just put...
layout 'admin', :only => [:index, :show]
... right after "before_filter" in "ContactsController", but, as I already have a bunch of other controllers with many actions properly being filtered as admin-required ones, it would be much easer if I could just reset the layout from "usual_layout" to "admin" inside the "admin_required" method.
BTW, by putting...
layout 开发者_开发问答'admin'
...inside "admin_required" (as I tried in the code above), I get an undefined method error message. It seems to work only outside of defs, just like I did for "usual_layout".
Thanks in advance.
From Rails guides, 2.2.13.2 Choosing Layouts at Runtime
:
class ProductsController < ApplicationController
layout :products_layout
private
def products_layout
@current_user.special? ? "special" : "products"
end
end
If for some reason you cannot modify the existing controller and/or just want to do this in a before filter you can use self.class.layout :special
here is an example:
class ProductsController < ApplicationController
layout :products
before_filter :set_special_layout
private
def set_special_layout
self.class.layout :special if @current_user.special?
end
end
It's just another way to do essential the same thing. More options make for happier programmers!!
The modern way of doing this is to use a proc,
layout proc { |controller| user.logged_in? "layout1" : "layout2" }
精彩评论