2010-10-11 4 views
1

J'écris une webapp dans Ruby on Rails 3. Rails 3 échappe automatiquement toutes les chaînes potentiellement mauvaises, ce qui est généralement une bonne chose, mais signifie que si vous assembler vous-même HTML, vous devez appeler html_safe dessus.Rails 3: Où un assistant utilisant h (c'est-à-dire html_escape) doit-il vivre?

J'ai un modèle de carte, qui a plusieurs champs de texte, dont le contenu n'est pas fiable (peut contenir du code HTML ou un script malveillant). J'ai une fonction qui effectue quelques transformations sur l'un de ces champs de texte, en utilisant d'autres connaissances sur la carte spécifique, pour produire une sortie HTML. Je veux intégrer le HTML produit par cette fonction à plusieurs endroits dans plusieurs parties de mon application.

Conceptuellement, cette aide concerne la vue. Cependant, je ne trouve aucun moyen d'écrire des fonctions dans mes fichiers View; il semble qu'ils doivent aller dans Helpers ou le contrôleur/modèle.

Comme cette fonction est très spécifique à un objet de la carte, la meilleure option serait d'avoir une fonction dans mon modèle de carte card.rb:

class Card < ActiveRecord::Base 
[...] 
def format(unsafe_text) 
    initial_text = h unsafe_text # aka html_escape unsafe_text 
    # assembles HTML output based on initial_text and fields of self 
    output_text.html_safe! 
end 

J'aimerais appeler cela en vues assorties en faisant des choses comme:

Rules text: <%= format(@card.rulestext) %> 

Cependant, il y a aussi un gros problème ici. Dans le modèle de carte card.rb, je suis en mesure d'utiliser la fonction html_safe!, mais je ne suis pas en mesure d'utiliser h ou html_escape. Il semble que les fonctions h et html_escape ne sont disponibles que dans les vues ERB, pas dans les helpers ou les contrôleurs!

Il existe quelques solutions de contournement. Je peux faire format pas désinfecte son entrée, et aller

Rules text: <%= format(h(@card.rulestext)) %> 

Mais c'est à la fois sujettes à dérapages dangereux (un manque h() et nous avons des problèmes) et est très non-DRY. En ce moment je suis sur un partiel pour avoir accès à la fonction h():

(in a normal view) 
Rules text: <%= render 'formattext', :text=> @card.rulestext %> 

(app/views/shared/_formattext.html.erb) 
<%= @card.format(html_escape(text)) %> 

Mais cela se sent toujours dangereux. Tout ce que j'ai à faire est de faire un seul appel oublieux à format(sometext) dans une vue, plutôt que d'appeler render 'formattext', :text=> sometext, et j'ai un texte sans échappement qui tourne autour.

Y a-t-il une meilleure façon de faire cela? Existe-t-il un moyen d'écrire des fonctions d'aide pour vivre dans la vue plutôt que dans le modèle ou le contrôleur?

+0

Fondamentalement, mon problème était que je ne me rendais pas compte de l'aide Les utilisateurs étaient directement associés à Views. Une fois que vous le savez, il devient plus évident qu'un CardHelper est le bon endroit pour le mettre. – AlexC

Répondre

2

Placez la logique qui fait votre ensemble de vue en CardHelper:

app/helpers/card_helper.rb

class CardHelper 
    def rules(card) 
    initial_text = h card.rules_text 
    # assembles HTML output based on initial_text and fields of card 
    output_text.html_safe 
    end 
end 

On ne sait pas à partir de votre exemple si vous voulez formater plusieurs champs via la méthode format. Si tel est le cas, alors vous pourriez être en mesure de le faire:

class CardHelper 
    def format(card, attribute) 
    initial_text = h card[attribute] 
    # assembles HTML output based on initial_text and fields of card 
    output_text.html_safe 
    end 
end 

Vous pouvez utiliser cette aide comme tout autre:

class CardsController 
    helper CardHelper 
end 

et votre point de vue:

<%= rules(@card) %> 

ou

<%= format(@card, :rules) %> 
+0

Donc les classes auxiliaires peuvent obtenir 'html_escape' et' h'? C'est seulement les classes modèles qui ne peuvent pas? Comme c'est étrange. – AlexC

+0

En fait, je ne suis pas sûr ... Sinon, vous pourriez toujours inclure le module 'ERB :: Util' dans vos classes auxiliaires. – Jacob

+0

Yup, juste vérifié. Toutes les méthodes d'assistance sont disponibles dans les classes Helper définies dans app/helpers. – Jacob

2

L'échappement du contenu pour la vue est une responsabilité de View, c'est la raison pour laquelle l'assistant h n'est pas disponible dans les contrôleurs ou les modèles. Cependant, je ne comprends pas pourquoi vous ne pouvez pas simplement nettoyer le contenu de la vue.

Notez également que, dans Rails 3, vous n'avez pas besoin d'appeler l'assistant h. Le contenu est automatiquement filtré par défaut, sauf si vous le marquez html_safe!.

La principale raison pour laquelle il n'est pas logique d'utiliser l'assistant h dans le modèle est que le modèle doit fonctionner indépendamment de la vue. En d'autres termes, le modèle ne devrait pas se soucier de savoir si le contenu va être incorporé dans un document HTML ou un fichier JSON (ce qui nécessite une approche d'échappement différente par rapport au HTML).

+0

Bon point. J'aimerais avoir l'aide dans la vue plutôt que dans le modèle, parce que c'est très conceptuellement à voir avec la vue. Mais il ne semble pas y avoir moyen d'écrire des fonctions d'aide dans ERB. Ce que je veux savoir, c'est où devrait aller l'assistant? (Je l'avais en tête en écrivant le titre de cette question, je vais éditer la question pour rendre cette requête plus claire.) – AlexC

+0

Et je sais que je n'ai pas besoin d'utiliser 'h' * sauf * J'utilise aussi' html_safe' . Mais j'utilise 'html_safe' pour les raisons que j'ai expliquées - j'assemble ma propre chaîne HTML. – AlexC

Questions connexes