Ruby, gsub and regex

Jim Neath picture Jim Neath · Aug 17, 2009 · Viewed 19.9k times · Source

Quick background: I have a string which contains references to other pages. The pages are linked to using the format: "#12". A hash followed by the ID of the page.

Say I have the following string:

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

I already know the IDs of the pages that need linking:

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

How can I loop through the page ids and link the #12 and #125 to their respective pages? The problem I've run into is if I do the following (in rails):

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

This works fine for #12 but it links the "12" part of #125 to the page with ID of 12.

Any help would be awesome.

Answer

sepp2k picture sepp2k · Aug 17, 2009

Instead of extracting the ids first and then replacing them, you can simply find and replace them in one go:

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

Even if you can't leave out the extraction step because you need the ids somewhere else as well, this should be much faster, since it doesn't have to go through the entire string for each id.

PS: If str isn't referred to from anywhere else, you can use str.gsub! instead of str = str.gsub