2010-10-11 5 views
1

J'ai un appel de méthode à mon avis comme celui-ciHTML dans Rails 3 échappé

<%= Navigation.with(params) do |menu| 
       if current_user && current_user.can_verify? 
       menu.item("Listings", manage_listings_path()) 
       menu.item("Listing changes", needing_change_approval_manage_listings_path()) 
       menu.item("Flagged Items", flagged_manage_listings_path()) 
       menu.item("Transfers", manage_listing_transfers_path()) 
       menu.item("Reviews", manage_listing_reviews_path()) 
       end 
       if current_user && current_user.admin? 
       menu.item("Log", manage_verifications_path()) 
       menu.item("Indexer Compensations", manage_compensations_path()) 
       menu.item("Users", manage_users_path()) 
       end 
      end%> 

qui sépare la chaîne ci-dessous

"<li><a href="/manage/listings" class="active">Listings</a></li> <li><a href="/manage/listings/needing_change_approval">Listing changes</a></li> <li><a href="/manage/listings/flagged">Flagged Items</a></li> <li><a href="/manage/listing_transfers">Transfers</a></li> <li><a href="/manage/listing_reviews">Reviews</a></li> <li><a href="/manage/verifications">Log</a></li> <li><a href="/manage/compensations">Indexer Compensations</a></li> <li><a href="/manage/users">Users</a></li>" 

Je viens d'obtenir cette chaîne dans ma page. Je voulais qu'ils soient des menus joliment stylisés par CSS. Je reçois juste le texte brut ci-dessus dans ma page. Comment puis-je convertir cette chaîne à traiter en HTML par le navigateur.

S'il vous plaît aider

Voici la classe de navigation

class NavigationMenu < ActionView::Base 
    def initialize(params) 
    @params = params 
    end 

    def item(title, path, options={}) 
    @items ||= Array.new 
    unless (route = Rails.application.routes.recognize_path(path,:method => options[:method]|| :get)) 
     raise "Unrecognised path #{path}, are you sure it's in routes.rb?" 
    end 

    @items << content_tag(:li, link_to(title,path, :class => (@params[:controller] == route[:controller] && @params[:action] == route[:action])? 'active' : nil)) 

    end 

    def output 
    return '' if @items.blank? 
    content_tag(:ul, @items.join("\n"), :id => 'navigation') 
    end 
end 

class Navigation 
    def self.with(params, &block) 
    menu = NavigationMenu.new(params) 
    yield menu 
    menu.output 
    end 
end 

Répondre

9

Vous devez ajouter un appel à la méthode raw:

<%= raw ... %> 

Cela est nécessaire, parce que dans Rails 3 chaque chaîne est échappé par défaut, sauf si vous utilisez la méthode raw. C'est comme l'inverse de la méthode h dans Rails 2, où chaque chaîne est décochée par défaut, sauf si vous utilisez la méthode h.

Exemple:

Ce code Rails 2 ...

<%= h "String which must be escaped" %> 
<%= "String which must be output raw %> 

... doit être cela dans Rails 3:

<%= "String which must be escaped" %> 
<%= raw "String which must be output raw %> 

(Même si un appel supplémentaire à h ne fait aucun mal dans Rails 3)

+0

J'ai enfermé l'appel de méthode dans raw() ...la chaîne n'est toujours pas considérée comme html – Anand

+1

Il est possible que la méthode 'Navigation.with' ne retourne pas vraiment de chaîne mais l'écrit directement dans la sortie. Dans ce cas, seul le développeur d'origine de 'Navigation' peut vous aider. –

+0

Ou vous partez à l'aventure dans les internals 'Navigation'. Apportez une machette. – Matchu

4

Vous devez ajouter .html_safe à la chaîne - cela empêchera les rails de l'échapper lorsqu'il est temps de sortir du texte. Probablement mieux de le mettre dans la méthode item que vous appelez à plusieurs reprises.

+0

J'ai mis la classe de navigation ci-dessus. S'il vous plaît aider – Anand

+0

Je ne sais pas exactement où/combien de fois vous avez besoin de l'appeler, mais tripoter avec 'html_safe'. Essayez de changer la dernière ligne de votre classe 'Navigation' en' menu.output.html_safe'. Si cela ne fonctionne pas, changez la dernière ligne de votre méthode 'item' en ceci:' @items << content_tag(). Html_safe'. Vous devrez peut-être faire la même chose partout où un 'content_tag' est. Non testé - vous devriez comprendre à partir de là cependant. – Jeriko

0

Voici la nouvelle classe. Enfin ... j'ai eu ce bug.

class NavigationMenu < ActionView::Base 
    def initialize(params) 
    @params = params 
    end 

    def item(title, path, options={}) 
    @items ||= Array.new 
    unless (route = Rails.application.routes.recognize_path(path,:method => options[:method]|| :get)) 
     raise "Unrecognised path #{path}, are you sure it's in routes.rb?" 
    end 

    @items << content_tag(:li, link_to(title,path, :class => (@params[:controller] == route[:controller] && @params[:action] == route[:action])? 'active' : nil)) 

    end 

    def output 
    @items = @items.join("\n").html_safe 
    return '' if @items.blank? 
    content_tag(:ul, @items, :id => 'navigation') 
    end 
end 

class Navigation 
    def self.with(params, &block) 
    menu = NavigationMenu.new(params) 
    yield menu 
    menu.output 
    end 
end 
+0

Peut-être pouvez-vous décrire le problème et accepter une réponse. –

1

j'ai écrit récemment un article concernant la protection XSS dans Rails 3 lors du passage de Rails 2: http://developer.uservoice.com/entries/upgrading-to-rails-3-printing-escaped-strings

L'idée est de relier le code à l'impression HTML afin que nous puissions déterminer quand nous fait imprimons quelque chose nous ne voulons pas:

module ActionView 
    module Helpers 
    module TextHelper 

     def simple_format_with_double_escape_reporting(*args) 
     HtmlDoubleEscapeReporter.assert_sane(simple_format_without_double_escape_reporting(*args)) 
     end 
     alias_method_chain :simple_format, :double_escape_reporting 
    end 

    module TagHelper 
     private 
     def content_tag_string_with_double_escape_reporting(*args) 
     HtmlDoubleEscapeReporter.assert_sane(content_tag_string_without_double_escape_reporting(*args)) 
     end 
     alias_method_chain :content_tag_string, :double_escape_reporting 
    end 
    module UrlHelper 
     def link_to_with_double_escape_reporting(*args, &block) 
     HtmlDoubleEscapeReporter.assert_sane(link_to_without_double_escape_reporting(*args, &block)) 
     end 
     alias_method_chain :link_to, :double_escape_reporting 
    end 
    end 
end 

Méthode HtmlDoubleEscapeReporter.assert_sane peut écrire, par exemple, comme ceci:

class HtmlDoubleEscapeReporter 
    def self.assert_sane(str) 
    if (str.match(/&lt;[a-z]/) || str.match(/&amp;(quot|rarr|larr|amp|#)/)) && 
     !str.match(/looks something you do not want to print/ 
     send_problem_report('#{str}' looks something you do not want to print") 
    end 
    return str 
    end 
end 

Ici, "regarde quelque chose que vous ne voulez pas imprimer" est utilisé pour éviter la possibilité de boucles infinies. La ligne send_problem_report ('# {str}' semble quelque chose que vous ne voulez pas imprimer ") peut être remplacée par un appel à" debugger "(à partir de ruby-debug gem) afin que vous puissiez vérifier la trace et voir où problème vient de

+0

Bienvenue dans Stack Overflow! Bien que cela puisse théoriquement répondre à la question, [il serait préférable] (http://meta.stackexchange.com/q/8259) d'inclure les parties essentielles de la réponse ici, et de fournir le lien pour référence. –

+0

Vrai! J'ai ajouté l'idée principale de l'article. –