Rails устанавливает макет из метода before_filter - PullRequest
20 голосов
/ 13 июля 2011

Возможно ли сбросить макет по умолчанию из метода before_filter в Rails 3?

У меня есть следующее как мой 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]

... сразу после "before_filter"в "ContactsController", но, поскольку у меня уже есть куча других контроллеров с многими действиями, должным образом отфильтрованными как необходимые для администратора, было бы намного проще, если бы я мог просто сбросить макет с "normal_layout" на "admin" внутриМетод "admin_required".

Кстати, помещая ...

layout 'admin'

... внутри "admin_required" (как я пытался в коде выше), я получаю неопределенную ошибку методасообщение.Кажется, что он работает только за пределами defs, как я сделал для "normal_layout".

Заранее спасибо.

Ответы [ 3 ]

68 голосов
/ 13 июля 2011

От Направляющие рельсы , 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
17 голосов
/ 04 октября 2011

Если по какой-то причине вы не можете изменить существующий контроллер и / или просто хотите сделать это в фильтре до, вы можете использовать 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 голосов
/ 21 июня 2016

Современный способ сделать это - использовать процедуру,

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