2009-08-17 8 views
9

Arrière-plan rapide: J'ai une chaîne qui contient des références à d'autres pages. Les pages sont liées à l'aide du format: "# 12". Un hachage suivi de l'identifiant de la pageRuby, gsub et regex

Dire que j'ai la chaîne suivante:

str = 'This string links to the pages #12 and #125' 

Je connais déjà les ID des pages qui ont besoin de liaison:

page_ids = str.scan(/#(\d*)/).flatten 
=> [12, 125] 

Comment puis-je boucle à travers la page ids et lier le # 12 et # 125 à leurs pages respectives? Le problème que j'ai rencontré est si je fais ce qui suit (en rails):

page_ids.each do |id| 
    str = str.gsub(/##{id}/, link_to("##{id}", page_path(id)) 
end 

Cela fonctionne bien pour # 12, mais elle relie la partie de # 125 à la page « 12 » avec l'ID de 12.

Toute aide serait géniale.

Répondre

12

si vos index se terminent toujours aux limites de mot, vous pouvez faire correspondre que:

page_ids.each do |id| 
    str = str.gsub(/##{id}\b/, link_to("##{id}", page_path(id)) 
end 

il vous suffit d'ajouter le mot symbole limite \b sur le modèle de recherche, il est nécessaire pour le modèle de remplacement.

+0

Merveilleuse. Je ne savais pas à propos de \ b. Vous monsieur, êtes un épargnant de vie. –

21

Au lieu d'extraire les IDs d'abord, puis les remplacer, vous pouvez simplement trouver et de les remplacer en une seule fois:

str = str.gsub(/#(\d*)/) { link_to("##{$1}", page_path($1)) } 

Même si vous ne pouvez pas laisser l'étape d'extraction car vous avez besoin quelque part les ids D'autre part, cela devrait être beaucoup plus rapide, car il n'a pas à parcourir toute la chaîne pour chaque identifiant.

PS: Si str n'est pas mentionné de nulle part ailleurs, vous pouvez utiliser str.gsub! au lieu de str = str.gsub

+2

C'est la bonne solution. – Magnar

+1

Ceci est efficace, mais, selon le contenu du texte, pourrait produire des faux positifs. Imaginez qu'il ait 125 pages à référencer et qu'il y ait des chaînes comme # 112325 dans le texte des pages (numéros de commande, etc ...) cela produirait un lien vers une page morte dans le cas de chaque faux positif. Bien que la recherche en utilisant la liste des pages et des limites de mots ne soit pas infaillible, elle est plus robuste que cette solution, malgré son élégance. – Pinochle

+2

S'il y avait une chaîne comme # 112325, elle serait dans le tableau page_ids, donc cela produirait un lien mort de toute façon. Notez que mon gsub utilise la même regex que l'analyse OP. Donc, ils vont trouver exactement les mêmes ID. – sepp2k