2009-08-17 11 views
9

Fondo rápido: tengo una cadena que contiene referencias a otras páginas. Las páginas están vinculadas al uso del formato: "# 12". Un hash seguido de la ID de la página.Ruby, gsub y regex

Decir que tengo la siguiente cadena:

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

que ya conoce el ID de las páginas que necesitan que unen:

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

¿Cómo puedo recorrer los ID de página y enlazar el # 12 y # 125 a sus respectivas páginas? El problema que he encontrado es que si hago lo siguiente (en rieles):

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

Esto funciona bien para # 12, pero que se vincula la parte "12" de # 125 a la página con los ID de 12.

Cualquier ayuda sería increíble.

Respuesta

12

si sus índices siempre terminan en los límites de palabra, puede coincidir con:

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

que sólo tiene que añadir la palabra límite del símbolo \b en el patrón de búsqueda, no es necesario que el patrón de sustitución.

+0

Maravillosa. No sabía sobre \ b. Usted señor, es un salvavidas. –

21

vez de extraer los identificadores primero y luego reemplazarlos, sólo tiene que buscar y reemplazar ellos de una sola vez:

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

Incluso si usted no puede dejar de lado la etapa de extracción, ya que necesita los identificadores de alguna parte también, esto debería ser mucho más rápido, ya que no tiene que pasar por la cadena completa para cada identificación.

PD: Si str no se conoce de ninguna otra parte, se puede utilizar en lugar de str.gsub!str = str.gsub

+2

Esta es la solución correcta. – Magnar

+1

Esto es eficiente, pero, según el contenido del texto, podría producir falsos positivos. Imagínese que tiene 125 páginas para referenciar y hay cadenas como # 112325 en el texto de las páginas (números de orden, etc.) Esto produciría un enlace a una página muerta en el caso de cada falso positivo. Si bien la búsqueda utilizando la lista de páginas y límites de palabras no es infalible, es más robusta que esta solución, a pesar de su elegancia. – Pinochle

+2

Si hubiera una cadena como # 112325, estaría en la matriz page_ids, por lo que produciría un vínculo inactivo en ambos sentidos. Tenga en cuenta que mi gsub utiliza la misma expresión regular que el escaneo de OP. Entonces encontrarán exactamente los mismos identificadores. – sepp2k