Rails在before_filter方法中设置布局

时间:2011-07-12 23:22:06

标签: ruby-on-rails layout before-filter

是否可以在Rails 3中的before_filter方法中重置默认布局?

我有以下 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

以下是我的 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

我知道我可以放......

layout 'admin', :only => [:index, :show]

...紧跟在“ContactsController”中的“before_filter”之后,但是,由于我已经有许多其他控制器,其中许多操作正确地被过滤为管理员要求的,所以如果我可以重置在“admin_required”方法中将“ordinary_layout”布局为“admin”。

顺便说一下,放......

layout 'admin'

...在“admin_required”里面(正如我在上面的代码中尝试过的那样),我得到一个未定义的方法错误消息。它似乎只在defs之外工作,就像我为“ordinary_layout”所做的那样。

提前致谢。

3 个答案:

答案 0 :(得分:68)

来自Rails guides2.2.13.2 Choosing Layouts at Runtime

class ProductsController < ApplicationController
  layout :products_layout

  private

  def products_layout
    @current_user.special? ? "special" : "products"
  end
end

答案 1 :(得分:17)

如果由于某种原因您无法修改现有控制器和/或只是想在之前的过滤器中执行此操作,您可以使用self.class.layout :special这里是一个示例:

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

这只是做同样事情的另一种方式。更多选择让更快乐的程序员!!

答案 2 :(得分:2)

这样做的现代方法是使用proc,

layout proc { |controller| user.logged_in? "layout1" : "layout2" }