2009-08-24 3 views
6

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

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) и использовать «если» заявление в вид.
  2. Используйте что-то вроде «after_filter» в контроллере адресов, чтобы отобразить другой макет.

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

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

ответ

9

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

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, er, необязательна и ссылается на макет в представлениях/макетах. Существуют различные другие варианты вызова рендеринга, которые вы можете найти в documentation for render.

+0

Спасибо. Но кажется, что если я это сделаю, я оставил бы путь «соглашения по конфигурации». Я немного волнуюсь - это мое первое приложение Rails - должен ли я уже отклоняться от того, что все остальные делают? – cite

+0

Ну, возможно, соглашение состоит в том, чтобы отобразить одно представление для действия, но я вижу, к чему вы клоните. Если вы просто ищете разные макеты, то решение Staelen является хорошим. Если вы действительно хотите отображать разные представления в зависимости от логики в действии, то я не уверен, что это достаточно близко к основному соглашению, чтобы уйти, не указав, какой вид вы хотите отобразить. – Shadwell

+0

Думаю, я попробую решение Стелена для макета и ваш вариант для шаблона, который будет отображаться. Еще раз спасибо. – cite

3

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

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, чтобы предоставить явный файл шаблона методу визуализации.

+0

Спасибо, Дейв. – cite

6

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

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 Поиск макеты

Надеется, что это помогает =)

+0

О, это хорошая идея. Большое спасибо! – cite

2

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

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

+0

Это. Ты был прав. Я попытался сделать слишком много вещей сразу - идея о том, чтобы все эти действия были спокойно доступны в двух режимах работы, была слишком интригующей. Я написал специальный контроллер администратора. Благодарю. – cite

0

Вы должны поместить административные действия в пространство имен администраторов и ограничить его там. Создайте папку с именем 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 тоже.

Смежные вопросы