2009-08-24 21 views
6

en mi aplicación, tengo un modelo de "Usuario". Cada usuario puede tener varias direcciones (correo electrónico) que se definen en el modelo de "Dirección":Un controlador, diferentes vistas para usuarios normales y administradores

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 

Dentro de la clase AddressController, el usuario actualmente conectado está disponible en la variable de instancia "@user". El controlador evita que los usuarios comunes editen, eliminen, visualicen direcciones etc. que no les pertenecen, pero permite que un usuario administrativo las edite. La clase AddressController puede preguntar al AddressModel si el usuario actualmente conectado está realizando operaciones normales o de superusuario.

Todo esto funciona bien y las actualizaciones de la base de datos se realizan como se esperaba, sin embargo, me gustaría tener diferentes vistas de HTML dependiendo del modo de operación. Sólo puedo pensar en dos formas de lograr que:

  1. Hacer el modo de funcionamiento (normal/privilegiada) conocidos en la clase AddressController (utilizando una variable de instancia, por ejemplo @privileged) y utilizar un "if" en la vista.
  2. Utilice algo así como un "after_filter" en el controlador de dirección para representar un diseño diferente.

Si es posible visualizar los resultados de ejecutar un solo controlador en dos diseños completamente diferentes, dependiendo de su modo de operación, ¿cuál es una buena manera de lograr eso?

Gracias de antemano Stefan

Respuesta

9

Puede especificar qué vista usar para mostrar el resultado de una acción en la acción misma. También puede especificar qué diseño usar. Así, por ejemplo:

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

Esto hará que sea admin_action.html.erb o non_admin_action.html.erb en función del valor de regresar de is_authorised. La opción :layout es, eh, opcional y se refiere a un diseño en vistas/diseños. Hay varias otras opciones, la llamada de renderizado que puede encontrar en el documentation for render.

+0

Gracias. Pero parece que si hago esto, dejaré el camino de "convención sobre configuración". Estoy un poco preocupado - esta es mi primera aplicación de Rails - ¿Debería ya diferir de lo que todos parecen hacer? – cite

+0

Bueno, podría decirse que es una convención presentar una vista para una acción, pero puedo ver a qué te refieres. Si solo está buscando diseños diferentes, entonces la solución de Staelen es buena. Si realmente desea renderizar diferentes vistas dependiendo de la lógica en la acción, entonces no estoy seguro de que esté lo suficientemente cerca de la convención básica para salirse con la suya sin especificar qué vista desea renderizar. – Shadwell

+0

Creo que probaré la solución de Staelen para el diseño y la de la plantilla para que se represente. Gracias de nuevo. – cite

3

sólo tiene que llamar al método render manualmente al final de la acción del controlador:

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

Esto hará que app/views/myview/show_privileged.html.erb o app/views/myview/show.html.erb. Alternativamente, puede usar la opción :template para dar un archivo de plantilla explícito al método de renderizado.

+0

Gracias, Dave. – cite

6

Puede especificar el diseño de la vista para ese controlador particular, o toda la aplicación en el controlador de aplicación por:

class SomeController < ApplicationController 
    layout :set_layout 

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

    ... 
end 

Usted puede tratar de averiguarlo aquí: http://guides.rubyonrails.org/layouts_and_rendering.html#using-render, bajo 2.2.12 encontrar diseños de

Espero que esto ayude =)

+0

Oh, esta es una buena idea. ¡Muchas gracias! – cite

2

Si este es el único controlador en su aplicación en la que estés, si/else'ing todo el lugar que es probablemente muy bien. Si comienza a hacer este tipo de lógica en todas partes, debería decirle que está haciendo demasiado a la vez.

La respuesta que usted aceptó (que está bien y funciona) tiene un diseño diferente y una vista diferente, para mí que dice que el controlador está haciendo demasiado; lo dividiría en un controlador de administrador.

+0

Esto. Usted tenía razón. Traté de hacer demasiadas cosas a la vez: la idea de tener todas esas acciones de manera descansada en dos modos de operación era demasiado intrigante. Escribí un controlador de administración dedicado. Gracias. – cite

0

Debe colocar acciones administrativas en un espacio de nombres administrativo y restringirlo allí. Crear un directorio llamado admin en el directorio de controladores y añadir un _application_controller.rb_ allí:

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 

Ahora usted puede poner controladores en este espacio de nombres y hacer que se heredan de Admin::ApplicationController también.

Cuestiones relacionadas