Один контроллер, разные представления для обычных пользователей и администраторов

StackOverflow https://stackoverflow.com/questions/1322189

Вопрос

в моем приложении у меня есть "пользовательская" модель.Каждый пользователь может иметь несколько адресов (электронной почты), которые определены в модели "Адрес".:

Class User < ActiveRecord::Base
  has_many :addresses


  def is_authorized(op)
     # returns true or false
  end

  def is_owned_by(user)
     # returns true or false
  end
end

Class Address < ActiveRecord::Base
  belongs_to :user
end

Внутри класса AddressController текущий вошедший в систему пользователь доступен в переменной экземпляра "@user".Контроллер запрещает обычным пользователям редактировать, удалять, просматривать и т.д.адреса, которые им не принадлежат, но он разрешает пользователю с правами администратора редактировать их.Класс AddressController может запросить AddressModel, выполняет ли пользователь, вошедший в систему в данный момент, обычные операции или операции суперпользователя.

Все это прекрасно работает, и обновления базы данных производятся, как и ожидалось, однако мне бы очень хотелось иметь разные представления HTML в зависимости от режима работы.Я могу придумать только два способа достичь этого:

  1. Сделайте режим работы (обычный / привилегированный) известным в классе AddressController (используя переменную экземпляра, например@privileged) и используйте оператор "if" в представлении.
  2. Используйте что-то вроде "after_filter" в контроллере адресов для отображения другого макета.

Если возможно отобразить результаты выполнения одного контроллера в двух совершенно разных макетах, в зависимости от его режима работы, каков хороший способ добиться этого?

Заранее спасибо Стефан

Это было полезно?

Решение

Вы можете указать, какое представление использовать для отображения результата действия в самом действии.Вы также можете указать, какой макет использовать.Так, например:

def my_action
  if @user.is_authorised(...)
    render :action => 'admin_action', :layout => 'admin'
  else
    render :action => 'non_admin_action', :layout => 'non_admin'
  end
end

Это приведет к тому, что либо admin_action.html.erb или non_admin_action.html.erb в зависимости от возвращаемого значения из is_authorised:layout опция, э-э, необязательна и ссылается на макет в views / layouts .Существуют различные другие варианты вызова рендеринга, которые вы можете найти в документация для рендеринга.

Другие советы

Вы можете указать макет представления для этого конкретного контроллера или всего приложения в application controller с помощью:

class SomeController < ApplicationController
  layout :set_layout

  def set_layout
    @user.is_authorized(...) ? "privileged_layout" : "normal_layout"
  end

  ...
end

Вы можете попытаться разобраться в этом здесь: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render, под 2.2.12 Поиск Макетов

Надеюсь, это поможет =)

Вы можете просто вызвать визуализировать используйте метод вручную в конце действия вашего контроллера:

if @privileged
    render :action => 'show_privileged'
else
    render :action => 'show'
end

Это окажет app/views/myview/show_privileged.html.erb или app/views/myview/show.html.erb.В качестве альтернативы, вы можете использовать :template возможность предоставить явный файл шаблона методу рендеринга.

Если это единственный контроллер в вашем приложении, где вы используете if / else повсюду, это, вероятно, нормально.Если вы начнете использовать этот тип логики везде, это должно сказать вам, что вы делаете слишком много сразу.

Ответ, который вы приняли (который прекрасен и работает!) имеет другой макет и другое представление, для меня это говорит о том, что контроллер делает слишком много - я бы разделил это на контроллер администратора.

Вы должны поместить административные действия в административное пространство имен и ограничить их там.Создайте каталог под названием admin в вашем каталоге контроллеров и добавьте туда _application_controller.rb_:

class Admin::ApplicationController < ApplicationController
  before_filter :check_authorized

  private
    def check_authorized?
      if !logged_in? || !current_user.admin?
        flash[:notice] = "You've been very bad. Go away.
        redirect_to root_path
      end
    end
 end

Теперь вы можете поместить контроллеры в это пространство имен и заставить их наследовать от Admin::ApplicationController слишком.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top