Clase del controlador actual desde una vista

De qué clase es self en una vista? Eso quiero saber pues necesito
acceder la clase del controlador actual desde la vista y me pareció que
self era un buen lugar para empezar. He definido variables/métodos de
clase en el controlador para encapsular funcionamiento común. Sé que
podría definir una varible de instance en el controlador y ahí guardar
la clase del controlador, pero me pareció poco elegante y repetitivo.

def una_accion_del_controlador

@clase_contolador = self.class

end

Entonces en la vista traté de obtener la clase de self pero para mi
sorpresa self no es ni Controlador ni Modelo ni nada conocido. Usé el
siguiente código de prueba:


<%
puts self.class
puts self.is_a?(Object)
puts self.is_a?(ApplicationController)
puts self.is_a?(Module)
puts self.is_a?(ActiveRecord::Base)
%>

Y retornó ésto en el log

#Class:0x3c38734
true
false
false
false

Otra forma que se me ocurre para obtener la clase del controlador actual
es: por medio de params[:controller] que contiene el nombre del
controlador actual, cómo convierto esta String en una clase?

En resumen, lo que necesito acceder la clase del controlador actual
desde la vista.

Gracias de antemano

PS: Para complicarlo aún más la vista en cuestión es el layout y uso el
mismo layout para todos las vistas

Me respondo

puts self.is_a?(ActionView::Base)

=> True

Para acceder el controlador actual desde la vista se usa

self.controller

Muchas Gracias a mi mismo :slight_smile:

On Oct 13, 2006, at 9:18 PM, Esteban wrote:

Otra forma que se me ocurre para obtener la clase del controlador
actual

En el contexto de una vista se tiene acceso al controlador via el metodo

controller

Pero de todas maneras lo que propones suena sospechoso. Un
controlador es responsable de preparar los datos necesario para
construir la vista, al mas alto nivel posible, pasarselos, y salir
del flujo. Si desde la vista has de volver al controlador (uso
“volver” para enfatizar que la comunicacion sobre el papel va en una
sola direccion) es muy posible que no estes aplicando bien el patron.

– fxn

Efectivamente como te comenta Xavier si necesitas pasar el controlador
como
variable a la vista, lo más probable es que tengas un error de concepto en
tu
aplicación.Es muy posible que lo que pretendes hacer se consiga o bien añadiendo al
modelo la funcionalidad que necesites (si se trata de la lógica de la
aplicación) o bien sacando el código a un helper(si lo que pretendes es
reutilizar funciones relacionadas con la vista de los datos).
Los métodos de un controlador tienen por misión manipular datos y redirigir
a la vista correspondiente. Volver de la vista al controlador antes de
llegar al usuario es incorrecto, o por lo menos no ortodoxo :slight_smile:

salu2,
Juanjo

----- Original Message -----

Xavier, Juanjo

Les planteo el sistema que estoy implementando en RoR
Dividamos los modelos en dos tipos: principales y secundarios, donde los
principales corresponden a aquellas tablas que existen por si mismas y
secundarias aquellas cuyos datos siempre referencian una llave de una
tabla principal. Ej: cliente es principal, transaccion es secundaria -
una transacción siempre está asociada a un cliente, etc.
Para cada tablas tienen un modelo, obvio. Y para cada modelo principal
existe un controlador asociado. Hay 2 tipos de modelos principales, en
unos se puede insertar/editar/borrar datos y en otros solo se puede
editar. Entonces pensé que este atributo lo podía guardar en el
controlador

class ControladorPrincipal < ActionController::Base
@@se_puede_insertar = true

def self.se_puede_insertar?
@@se_puede_insertar
end

def self.se_puede_insertar=(value)
@@se_puede_insertar = value
end

end

class ControladorPrincipalConInsert < ControladorPrincipal

end

class ControladorPrincipalSinInsert < ControladorPrincipal
self.se_puede_insertar = false

end

El atributo lo guardo en el controlador porque

  • la relación entre los controladores principales y los modelos
    principales es 1:1
  • la acción new del controlador inserta un nuevo item en el modelo,
    entonces en la vista pongo <%= link_to (“Insertar Nuevo”, :action =>
    :new) if self.controlador.class.se_puede_insertar %>

En cambio si el atributo estuviera en el modelo, cómo acceso el modelo
del controlador actual desde la vista? Se me ocurre guardar una
referencia del modelo en el controlador y luego accederlo así desde la
vista: self.controller.model.class.se_puede_insertar, pero creo que es
una versión peor a la anterior: self.controlador.class.se_puede_insertar

Aunque me han dado de que pensar, creen que mi código necesita un
refactorización?

On Oct 14, 2006, at 12:45 AM, Esteban wrote:

Aunque me han dado de que pensar, creen que mi código necesita un
refactorización?

Por que codificas tanta metainformacion?

Estas cosas suelen ser mas sencillas, uno decide que controladores
quiere, sin acoplarlos al modelo aunque en su organizacion el modelo
puede que influya, y en la vista el programador pone un enlace o no a
crear tal modelo en funcion de si va o no va, como cualquier otro
enlace. Por lo que explicas parece que pones enlaces a crear modelo
en todos los lugares donde podria tener sentido y los condicionas a
esa metainformacion.

Ese diseño en mi opinion es algo rigido y mezcla las tres capas, ya
que establece una relacion entre controladores y modelos principales
que luego percola a las vistas. O es que estas haciendo algun
generador de codigo o algo asi?

– fxn

Para este caso se me ocurre que un respond_to? es la solución

<%= link_to (“Insertar Nuevo”, :action => :new) if
self.controlador.respond_to?(:new) %>

Pero la pregunta que hice antes sigue vigente: Cómo acceso el modelo del
controlador actual desde la vista?

No seáis tan talibanes que no hay nada malo en acceder a otra ‘capa’ del
patrón MVC. Por algo desde una vista tenemos disponible la variable
controller. Con controller.class accedes a su clase.

Juanjo Bazán escribió:

Digamos que mucha programación de esta app se beneficiaría de usar un
generador de código especifico para esta app.
Estoy migrando una app que usa una legacy DB a RoR. Mucha de la
funcionalidad que tengo que programar es parecida a un scaffold: (list,
new, edit, show), aunque no tan simple como el scaffold que trae RoR. Me
inspirado un poco en una app de RoR GAL http://gal.railsplayground.com/
y en el gem Streamlined http://streamlined.relevancellc.com/
El código de la app que estoy migrando en gran parte se puede resolver
con un scaffold personalizado, otra parte con programción pura y dura, y
el resto con trucos de Ruby.

Por ejemplo de trucos de Ruby: En la tabla de usuarios hay una columna
donde dice si se tiene o no acceso a un módulo de la app. Vooy a
programar cada módulo como un controlador, entonces hice hash de
controlador => nombre_columna_con_acceso. Entonces con un before filter
valido el acceso

def tiene_acceso
if Usuario.find(:first,
session[:userid]).send(modulos_derechos_hash[params[:controller]]) > 0
# tiene acceso
else
# no tiene acceso
end
end

Mucha funcionalidad de la aplicación se puede resumir en listar,
insertar, editar, borrar; cómo el scaffold que viene con RoR. De hecho
cada módulo principal muestra una lista paginada del modelo - con
filtros y ordenamiento por columna. Para cada fila tenemos las
funcionalidad: show, edit y delete. Y a nivel del layout (que es común
para los controladores principales) la opcion de insertar - si se puede
insertar.
Si creo que es rigido pero esa es mi intención. Quiero que todos los
controladores principales se vean y funcionen iguales, así a los
usuarios no les costará aprender a usar la app.

La programación pura y dura se dará más adelante, para los casos
especiales, aunque -espero- no sea tan dura.

Saludos

On Oct 14, 2006, at 8:06 AM, Josh | Vectrice wrote:

No seáis tan talibanes que no hay nada malo en acceder a otra
‘capa’ del patrón MVC. Por algo desde una vista tenemos disponible
la variable controller. Con controller.class accedes a su clase.

Estas cosas no son ni malas ni buenas en terminos absolutos. El
patron MVC no es una verdad platonica! :slight_smile:

Ocurre como con los warnings, ante un warning tate, casi nunca me ha
pasado que no tuviera detras un bug. Igualmente desviaciones del
patron (si la intencion es seguirlo, que se asume en Rails) hay que
analizarlas porque es raro que no tengan detras un “error” de diseño.
No es por capricho ni por ganas de tener bonitos diagramas que se
sigue el patron MVC, se sigue porque la experiencia muestra que
permite construir web sites bien organizados. La consecuencia de
mezclar responsabilidades no es desagrado estetico, es que la
implementacion se lia.

Igualmente, cuando alguien pregunta como podria acceder a la sesion
desde un modelo la respuesta unanime es que no tendria que serle
necesario. Lo que el modelo necesite viniendo de la interfaz se lo
tiene que proporcionar el controlador. Es sospechoso que te haga
falta. Eso se señala con voluntad de ayudar, por el bien del codigo,
no por querer hacer seguir ciegamente un patron.