2008/2/28 Fernando C. [email protected]:
Esto funciona bien, pero es feo porque mete en la vista una carga de
datos que debería estar en el controlador. ¿Cómo podría resolver esto de
una forma más elegante?
s2 y gracias
Hay varios problemillas con tu código, obviamente el primero ya lo
comentas tú: pones en la vista lógica de la aplicación, lo que no es
nada recomendable. Pero supongamos que no tenemos problemas con eso
(por ahora).
Para obtener los mensajes de un tipo utilizas :conditions => “tipo_id
= #{tipo}” que tiene dos problemas. En tú caso un problema de
inyección de código es difícil, pero sería recomendable que en esas
cadenas de conditions, permitieras a Rails que te protegiera
utilizando :conditions => { :tipo_id => tipo.id }.
Pero además no necesitas construir tú mismo las condiciones SQL cuando
tienes una relación has_many/belongs_to entre los modelos Tipo y
Mensaje, desde un objeto de clase Tipo puedes utilizar el método
mensajes y desde un objeto de clase Mensaje el método tipo, incluso
con finders y demás cosas que te proporciona Rails. De forma que tu
línea para recupera mensajes sería:
@mensajes = tipo.mensajes.find(:limit => 3, :order => ‘created_at DESC’)
Mi recomendación sería seguir eliminando lógica de la vista y crear un
nuevo método en mensajes llamado ultimos que precisamente hiciera esa
búsqueda:
class Mensaje
def self.ultimos(limit = 3) # Por defecto 3, pero se puede modificar
al llamar al método
find(:limit => limit, :order => ‘created_at DESC’)
end
end
Un método que mágicamente Rails te permite utilizar “a través” de una
asociación:
@mensajes = tipo.mensajes.ultimos
El último problema de tu código es el “temido” problema de las n+1
consultas: tú código hace una primera consulta para obtener todos los
tipos, y luego, para cada uno de ellos (n) hace otra consulta para
obtener los tres últimos mensajes. Normalmente ese problema se
resuelve con lo que se denomina “eager_loading”, utilizando la
opción:include de Rails o algo similar, pero no consigo ver con tus
condiciones sobre los mensajes como se puede obtener los últimos tres
de cada tipo directamente desde la base de datos. Quizá alguien con
más experiencia en SQL puede ver una
solución.
Suerte.