2011-06-07 14 views
6

Tengo un modelo llamado Feature con una variable llamada body_string, que contiene etiquetas HTML que me gustaría mostrar, en lugar de escapar.¿Hay alguna forma de definir el atributo de un modelo como siempre html_safe?

Cada vez que hago referencia a body_string en mis vistas, necesito usar <%=raw o .html_safe. Esto parece redundante y no tan SECO.

¿Hay alguna manera de que pueda establecer una vez y para todos la variable body_string como html_safe?

Supongo que esto sucedería en el archivo app/models/feature.rb, pero no puedo entender cuál sería exactamente la sintaxis correcta. Pensé en esto:

def body_string 
    return self.body_string.html_safe 
end 

Pero a Rails no le gusta; levanta una excepción stack level too deep.

Naturalmente, podría definir una variable/método con un nombre diferente:

def safe_body_string 
    return self.body_string.html_safe 
end 

Y luego simplemente cambiar todas las referencias en los puntos de vista body_string-safe_body_string. Pero de alguna manera esto parece casi tan seco como simplemente usar raw o .html_safe en primer lugar.

¿Alguna idea de cómo manejar mejor esto? Siento que debe haber algo realmente elegante que no estoy viendo.

+4

Probablemente deberías usar 'raw' cada vez que desees generar' body_string', independientemente de DRY (solo 3 caracteres). Hay una razón por la que se ve obligado a ser muy explícito cuando intenta generar un código HTML no codificado, y los desarrolladores esperan * ver * que usted sea explícito.Está moviendo efectivamente la lógica de visualización al modelo y está haciendo que sea mucho menos obvio para las personas que buscan sus vistas que el HTML sin procesar se envía al navegador. – meagar

+0

Lamento tener solo un voto alternativo para dar al comentario de @ meagar – Simon

Respuesta

9

Sólo tiene que utilizar read_attribute para evitar la llamada recursiva a body_string:

def body_string 
    read_attribute(:body_string).html_safe 
end 

read_attribute se complementa con write_attribute para el establecimiento de atributos desde el interior de su modelo.

Una nota sobre el estilo: No use returns explicitas a menos que realmente las necesite. El resultado de la última instrucción en un método es implícitamente el valor devuelto por el método.

+1

Cambiaría a read_attribute (: body_string) .try (: html_safe), por lo que no arrojará errores cuando el atributo sea nulo –

0

O también puede utilizar este enfoque,

def body_string 
    super && super.html_safe 
end 
1

Mientras @ respuesta de magro sin duda va a funcionar, no creo que esta lógica pertenece en un modelo. Simplemente porque agrega preocupaciones a nivel de vista (seguridad de HTML) a la capa de modelo, que solo debe incluir lógica comercial. En cambio, recomendaría usar un Presentador para esto (vea http://nithinbekal.com/posts/rails-presenters/ o encuentre una joya para esto - Personalmente amo Display Case). Su presentador puede anular fácilmente el método body_string y proporcionar la designación .html_safe cuando se muestra en la vista. De esta manera, separa sus preocupaciones y puede continuar obteniendo body_string de otros modelos sin mezclar en la vista.

Cuestiones relacionadas