Como usar una variable en un layout


#1

Veréis tengo el siguiente código en un layout:

<% if !current_user.club.season.round_actual.nil? %>


<% match = current_user.club.season.round_actual.get_match(@club)
%>
<%= “#{h(match.local.name)} #{match.local_goals}
- #{h(match.guest.name)} #{match.guest_goals}” %>

<% end %>

Pero veo bastante mal tener que declarar una variable dentro de una
vista, ¿Cómo puedo sacarla del layout? ¿Dónde he de escribir el código?


#2

En el controlador creo yo ¿no?

El 12 de mayo de 2009 18:49, Carlos Belizón <
removed_email_address@domain.invalid> escribió:


#3

Andrés Gutiérrez wrote:

En el controlador creo yo ¿no?

El 12 de mayo de 2009 18:49, Carlos Belizón <
removed_email_address@domain.invalid> escribió:

¿Pero en qué parte? Teniendo en cuenta que el layout se ejecuta que
cualquier acción, ¿Dónde he de recuperar el valor?


#4

Si la variable match la necesitas en todas las acciones de todos los
controladores, en el aplication controller hace algo asi

class ApplicationController < ActionController::Base
before_filter :set_match

def set_match
@match = current_user.club.season.round_actual.get_match(@club)
end

y la tendras disponible en cualquier vista

2009/5/12 Carlos Belizón removed_email_address@domain.invalid:


Ror-es mailing list
removed_email_address@domain.invalid
http://lists.simplelogica.net/mailman/listinfo/ror-es


#5

Fernando C. wrote:

Mejor aún:

class ApplicationController < ActionController::Base
before_filter :set_match

def set_match
if !current_user.club.season.round_actual.nil?
@match = current_user.club.season.round_actual.get_match(@club)
end
end

Hey, muchas gracias, no sé como no se me ocurrió esa “chorrada”. Acabas
de salvarme la vida ;).


#6

Mejor aún:

class ApplicationController < ActionController::Base
before_filter :set_match

def set_match
if !current_user.club.season.round_actual.nil?
@match = current_user.club.season.round_actual.get_match(@club)
end
end


<%- if @match -%>


<%= “#{h(@match.local.name)} #{@match.local_goals}
- #{h(@match.guest.name)} #{@match.guest_goals}” %>

<%- end -%>

#7

Xavier N. wrote:

Te queria comentar también que estan que esta

current_user.club.season.round_actual.nil?

es una condicion demasiado complicada para una vista. Ahi parece que
sea necesario un metodo en User que encapsule lo que significa
club.season.round_actual.nil?, y una variable en el controller que
haga de simple flag para el if.

Hey, muchas gracias, he hecho lo que dices y el código ahora es
muchísimo más legible.


#8

Te queria comentar tambien que esta

current_user.club.season.round_actual.nil?

sea necesario un metodo en User que encapsule lo que significa
club.season.round_actual.nil?, y una variable en el controller

de hecho, esa condición no es solamente muy complicada para una vista,
sino para cualquier sitio. Atendiendo a la ley de demeter (don’t talk to
strangers), deberías ejecutar métodos solamente sobre tu objeto o sobre
los objetos inmediatamente conectados a él. Es decir, que podrías hacer
algo como

class User
def round_actual?
club.round_actual?
end
end

y dentro de club

class Club
def round_actual?
season.round_actual?
end
end

y dentro de season

class Season
def round_actual?
round_actual.nil?
end
end

Aplicando esto, tu código es más robusto de cara a posibles cambios en
el futuro y como efecto colateral te permite realizar los tests de forma
más simple (para probar el objeto User no necesitas tener un
club/season/round_actual. Te vale con el método round_actual?)

saludos,

j


javier ramírez

…i do ruby on rails development in madrid, spain, at
http://www.aspgems.com
…you can find out more about me on http://formatinternet.wordpress.com
and http://workingwithrails.com/person/5987-javier-ramirez


#9

2009/5/12 Carlos Belizón removed_email_address@domain.invalid:

Veréis tengo el siguiente código en un layout:

<% if !current_user.club.season.round_actual.nil? %>

Te queria comentar tambien que esta

current_user.club.season.round_actual.nil?

es una condicion demasiado complicada para una vista. Ahi parece que
sea necesario un metodo en User que encapsule lo que significa
club.season.round_actual.nil?, y una variable en el controller que
haga de simple flag para el if.


#10

class Season
def round_actual?
round_actual.nil?
end
end

Aplicando esto, tu código es más robusto de cara a posibles cambios en

antes de que nadie me diga nada :wink: … Es muy posible que puedas usar
directamente :delegate para ahorrarte los métodos intermedios y dejar
que ruby lo haga por ti. El efecto final es el mismo


javier ramírez

…i do ruby on rails development in madrid, spain, at
http://www.aspgems.com
…you can find out more about me on http://formatinternet.wordpress.com
and http://workingwithrails.com/person/5987-javier-ramirez


#11

javier ramirez wrote:

de hecho, esa condición no es solamente muy complicada para una vista,
sino para cualquier sitio. Atendiendo a la ley de demeter (don’t talk to
strangers), deberías ejecutar métodos solamente sobre tu objeto o sobre
los objetos inmediatamente conectados a él. Es decir, que podrías hacer
algo como

class User
def round_actual?
club.round_actual?
end
end

y dentro de club

class Club
def round_actual?
season.round_actual?
end
end

y dentro de season

class Season
def round_actual?
round_actual.nil?
end
end

Aplicando esto, tu código es más robusto de cara a posibles cambios en
el futuro y como efecto colateral te permite realizar los tests de forma
más simple (para probar el objeto User no necesitas tener un
club/season/round_actual. Te vale con el método round_actual?)

Eso es muy bonito en teoría, pero por cada nivel vas a hacer un acceso a
base de datos: tu aplicación irá lenta, y tu servidor irá cargado. Lo
suyo para este caso sería replicar la información tantas veces como haga
falta, y que todas las tablas (User, Club, Season) tuvieran un campo
“round_actual” (o mejor: “jornada_actual” o “current_round”, para no
hablar espanglis) que se pudiera consultar directamente con un único
acceso. Eso complica un poco el proceso de cambio de jornada, pero la
ganancia en simplicidad y velocidad del código lo compensa con creces…
Más que nada, porque van a haber muchísmos más READs de la jornada
actual que WRITEs, por lo que conviene optimizar el READ.

s2


#12

Eso es muy bonito en teoría, pero por cada nivel vas a hacer un acceso a
base de datos: tu aplicación irá lenta,
no tiene porqué. Si al cargar el user has lanzado los includes
necesarios, no estás ejecutando más que la consulta inicial a la db. De
hecho tal cuál funciona Rails ahora mismo, aunque uses includes vas a
acabar teniendo n consultas (una por cada tabla asociada) así que sería
lo mismo.

En realidad he entrado al thread no por el caso concreto de estos
modelos o del rendimiento (que no parece crítico en esta aplicación),
sino por la parte de tener un statement excesivamente complicado que te
fuerza a tener un acoplamiento grande.

Creo que es interesante dedicar tiempo a que tu código quede bien
estructurado e incluso en algunas ocasiones aunque resultase en un
rendimiento peor (que no tiene porqué ser el caso esta vez)

saludos,

j


javier ramírez

…i do ruby on rails development in madrid, spain, at
http://www.aspgems.com
…you can find out more about me on http://formatinternet.wordpress.com
and http://workingwithrails.com/person/5987-javier-ramirez


#13

Eso es muy bonito en teoría, pero por cada nivel vas a hacer un acceso a
base de datos: tu aplicación irá lenta,

La solucion que te ha comentado Javier, a parte de estar mucho mejor
que la tuya en cuanto, no solo a “belleza del codigo” sino a
estructuracion, no es mas lenta que la tuya, pruebalo.


#14

No solo tiene que estar bien estructurada, también habría que ver si se
puede optimizar algo mas.

No hacer llamadas a la DB desde una vista por ejemplo puede hacer un
gran
efecto, y esto lo consigue con un simple “include”.

Ejem: User.find :all, :include => [:profiles, friends]

Si pudieras pegarnos un trozo del log de una vista de Verema seguro que
podríamos ayudarte a optimizarla.

2009/5/18 Fernando C. removed_email_address@domain.invalid


#15

javier ramirez wrote:

no tiene porqué. Si al cargar el user has lanzado los includes
necesarios, no estás ejecutando más que la consulta inicial a la db. De
hecho tal cuál funciona Rails ahora mismo, aunque uses includes vas a
acabar teniendo n consultas (una por cada tabla asociada) así que sería
lo mismo.

O no me he explicado, o no me has entendido: mi propuesta es guardar una
copia del dato en la propia tabla (cachearlo permanentemente, vamos), y
eso supone que está accesible en una única consulta.

El rendimiento (que no parece crítico en esta aplicación).

Creo que es interesante dedicar tiempo a que tu código quede bien
estructurado e incluso en algunas ocasiones aunque resultase en un
rendimiento peor (que no tiene porqué ser el caso esta vez)

Emili Parreño wrote:

La solucion que te ha comentado Javier, a parte de estar mucho mejor
que la tuya en cuanto, no solo a “belleza del codigo” sino a
estructuracion, no es mas lenta que la tuya, pruebalo.

De la mejor estructuración no tengo ninguna duda, y quizá sea cierto que
aquí el rendimiento no vaya a ser crítico (aunque a mí me gusta
optimizar el rendimiento por sistema, aun sin ser crítico). Pero en
cuanto a rendimiento, es algo que ya he probado, y no con logs, sino con
aplicaciones reales, http://www.verema.com/ y http://www.rankia.com/ ,
de más de millón y medio de páginas al mes…

Verema está hecha “bien estructurada”, pero me paso el tiempo
consultando para cada contenido cuál es el nombre del subtipo (vía
subtipo_id) y el nombre del autor (vía usuario_id). Para Rankia, estos
datos y algunos pocos más están cacheados en la tabla que frecuentemente
los consulta, rompiendo la “estructuración”… pero la diferencia de
resultados que da newrelic es apreciable:
Tiempo de respuesta: 160 => 105
Consumo de CPU, memoria y BBDD: 9,5%, 582 MB y 19,3% => 6,6%, 358 MB y
9,8%

(Datos de la media semanal del último informe de newrelic; ambas están
alojadas en la misma máquina y con la misma configuración)

Aparte de que no necesito que newrelic lo diga… con ver los logs de
desarrollo y las consultas a BBDD que se están generando en cada caso,
ya se nota.

s2


#16

que yo sepa, desde mysql 5 ya metieron el tema de los triggers y
procedimientos almacenados(aunque no tengo ni idea si la implementación
es
comparable a la de postgres)

2009/5/20 Benjamín Cárdenas Salamandra removed_email_address@domain.invalid


#17

Ror-es mailing list
removed_email_address@domain.invalid
http://lists.simplelogica.net/mailman/listinfo/ror-es


#18

Ceritium wrote:

No solo tiene que estar bien estructurada, también habría que ver si se
puede optimizar algo mas.

No hacer llamadas a la DB desde una vista por ejemplo puede hacer un
gran
efecto, y esto lo consigue con un simple “include”.

Ejem: User.find :all, :include => [:profiles, friends]

Si pudieras pegarnos un trozo del log de una vista de Verema seguro que
podríamos ayudarte a optimizarla.

2009/5/18 Fernando C. removed_email_address@domain.invalid

No creas que es sólo eso… te aseguro que las optimizaciones triviales,
y algunas no tan triviales, ya están hechas, y los índices en su sitio,
y todo bien repasado con el newrelic (muy recomendable) para encontrar y
corregir cuellos de botella. Pero mira por ejemplo la página índice del
foro de gastronomía:
http://www.verema.com/foros/gastronomia/temas

Tengo que sacar los 25 últimos hilos, y para cada uno de ellos la última
respuesta, y para el inicio de hilo y la última respuesta tengo que
acceder al usuario correspondiente; con tablas de decenas de miles y
cientos de miles de registros, cada una de ellas. La SQL (una sola, of
course!!) está ya muy pulida… pero si le ahorras tener que cruzar los
contenidos (hilo y última respuesta) con la tabla usuarios, consigues
que vaya mejor. No es que así vaya mal, de hecho Verema tiene muy buenos
tiempos… pero Rankia los tiene aún mejores, y además no podría
mantener cinco Veremas en mi servidor, y sí que podría mantener cinco
Rankias.

s2


#19

2009/5/22 Gunnar W. removed_email_address@domain.invalid

Saludos,

FLAMEBAIT ALERT! ¡DEJEN PASO A LOS CAZAFANTAMAS!

Vamos a cuidar un poco el lenguaje. Mysql no sería una base de datos
seria
si me la hubiese encontrado borracha y tirada en la calle hoy al venir a
trabajar (y si ella no tuviese festivo hoy)
Como no es el caso, dejémoslo en que tiene ventajas e inconvenientes. De
lo
contrario tenemos que armar un complejísimo conjunto de teorías para
entender cómo es que X se decanta por Mysql para montar Y (1) ,
descartando
que a) X no son serios b) no entienden de qué va el tema y c) Y no sea
un
éxito tecnológico/financiero/empresarial

Sobre lo de InnoDB, hay muchas discusiones interesantes donde te
encuentras
opiniones diversas, como por ejemplo:
““MyISAM is faster” is a myth propagated by benchmark junkies who have
no
experience with real-world applications.” (2)

Y dicho esto, vamos a cerrar el hilo, que el flamebait sin haber bebido
nada
antes me da ardor de estómago y las discusiones sobre “X IS TEH SUCK / Y
ROCKS” me provocan astenia metafísica

(1) http://www.mysql.com/customers/industry/?id=85
(2)
http://mysqlha.blogspot.com/2009/01/innodb-is-faster-tcmalloc-is-nice.html?showComment=1232243640000


#20

Borja Martín dijo [Wed, May 20, 2009 at 12:29:32PM +0200]:

que yo sepa, desde mysql 5 ya metieron el tema de los triggers y
procedimientos almacenados(aunque no tengo ni idea si la implementación es
comparable a la de postgres)

MySQL no es una base de datos seria. Y no, no lo digo de broma de
ninguna manera. Es una BD qu eno implementa decentemente el estándar
SQL; la integridad referencial ya existe, pero requiere que uses un
tipo de tabla ridículamente lento (lo de MyISAM vs. InnoDB). Hay
muchas condiciones que te llevan a valores sin sentido (p.ej. la fecha
00-00-0000 es válida)… Si quieres una base de datos de verdad, usa
PostgreSQL.

Saludos,


Gunnar W. - removed_email_address@domain.invalid - (+52-55)5623-0154 / 1451-2244
PGP key 1024D/8BB527AF 2001-10-23
Fingerprint: 0C79 D2D1 2C4E 9CE4 5973 F800 D80E F35A 8BB5 27AF