2009-08-24 13 views
6

w mojej aplikacji, mam model "użytkownika". Każdy użytkownik może mieć wiele adresów (email), które są zdefiniowane w modelu „Adres”:Jeden kontroler, różne widoki dla zwykłych użytkowników i administratorów

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 

Wewnątrz klasy AddressController, aktualnie zalogowanego użytkownika jest dostępny w „@user” zmiennej instancji. Sterownik uniemożliwia zwykłym użytkownikom edytowanie, usuwanie, przeglądanie itp. Adresów, które nie należą do nich - ale zezwala użytkownikowi administracyjnemu na ich edycję. Klasa AddressController może zwrócić się do AddressModel, jeśli aktualnie zalogowany użytkownik wykonuje operacje normalne lub superuser.

Wszystko działa ładnie, a aktualizacje bazy danych są wykonywane zgodnie z oczekiwaniami, jednak chciałbym mieć różne widoki HTML w zależności od trybu działania. Mogę myśleć tylko dwa sposoby, aby to osiągnąć:

  1. Bądź tryb pracy (normalny/uprzywilejowane), znany w klasie AddressController (przy użyciu zmiennej instancji, np @privileged) i używać „if” w widok.
  2. Użyj czegoś w stylu "after_filter" w kontrolerze adresu, aby wyświetlić inny układ.

Jeśli możliwe jest wyświetlanie wyników wykonywania pojedynczego kontrolera w dwóch całkowicie różnych układach, w zależności od jego trybu działania, jaki jest dobry sposób na osiągnięcie tego?

góry dzięki Stefana

Odpowiedz

9

Można określić, który widok ma być używany do wyświetlania wyniku działania w samym działaniu. Możesz także określić, który układ również będzie używany. Tak więc, na przykład:

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

To będzie świadczyć albo admin_action.html.erb lub non_admin_action.html.erb zależności od zwracanej wartości z is_authorised. Opcja :layout jest opcjonalna i odsyła do układu w widokach/układach. Istnieje wiele innych opcji wywołania renderowania, które można znaleźć w documentation for render.

+0

Dziękuję. Ale wydaje się, że jeśli to zrobię, zostawię ścieżkę "konwencji ponad konfigurację". Trochę się martwię - to moja pierwsza aplikacja Railsowa - czy powinienem już odejść od tego, co wszyscy inni robią? – cite

+0

Cóż, prawdopodobnie konwencją jest przedstawienie jednego spojrzenia na działanie, ale widzę, do czego dążysz. Jeśli szukasz tylko różnych układów, rozwiązanie Staelen jest dobre. Jeśli naprawdę chcesz renderować różne widoki w zależności od logiki w akcji, nie jestem pewien, czy jest wystarczająco blisko podstawowej konwencji, aby uciec od określania widoku, który chcesz renderować. – Shadwell

+0

Myślę, że spróbuję rozwiązania Staelena dla układu i twojego dla szablonu, który ma być renderowany. Dzięki jeszcze raz. – cite

3

można po prostu wywołać metodę render ręcznie na końcu swojego działania kontrolera:

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

To uczyni app/views/myview/show_privileged.html.erb lub app/views/myview/show.html.erb. Alternatywnie można użyć opcji :template, aby podać jawny plik szablonu do metody renderowania.

+0

Dziękuję, Dave. – cite

6

Można określić układ widoku dla danego sterownika lub całej aplikacji w kontrolerze aplikacji przez:

class SomeController < ApplicationController 
    layout :set_layout 

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

    ... 
end 

można spróbować ustalić to tutaj: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render pod 2.2.12 znalezienie układów

Nadzieja to pomaga =)

+0

To fajny pomysł. Dziękuję Ci bardzo! – cite

2

Jeśli jest to jedyny kontroler w aplikacji, gdzie jesteś, jeśli/else'ing wszędzie to chyba dobrze. Jeśli zaczniesz robić tego typu logikę wszędzie, gdzie powinieneś powiedzieć, że robisz za dużo naraz.

Odpowiedź, którą zaakceptowałeś (co jest w porządku i działa!) Ma inny układ i inny widok, co oznacza, że ​​kontroler robi za dużo - podzieliłbym to na kontrolera administratora.

+0

To. Miałeś rację. Próbowałem robić zbyt wiele rzeczy naraz - pomysł, by wszystkie te działania były dostępne w dwóch trybach, był zbyt intrygujący. Napisałem dedykowanego kontrolera administratora. Dzięki. – cite

0

Powinieneś umieścić działania administracyjne w administracyjnej przestrzeni nazw i tam je ograniczyć. Utwórz katalog o nazwie admin w katalogu sterowników i dodać _application_controller.rb_ tam:

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 

Teraz można umieścić kontrolery do tej przestrzeni nazw i uczynić je dziedziczyć Admin::ApplicationController też.

Powiązane problemy