1

我有一个 Rails 应用程序,我正在编辑文本并允许类似 wiki 的链接。我已经让它工作了,所以你可以在描述中写 [[:slug]] ,它会生成相关页面的链接,链接文本是保存在数据库中的名称。我想做这样我就可以写 [[:slug | Some Text]] 并且链接会显示“Some Text”而不是名称。此外,我想让它可选地包含自定义链接文本。

这是我正在使用的代码。

def replace_slugs(text)
  slugs = text.scan(/\[{2}:([^\]]*)\]{2}/).map{|s|s[0]}
  Character.where(:slug => slugs).each{|ch| text.gsub!("[[:#{ch.slug}]]",
    link_to(ch.name, adventure_character_path(ch.adventure, ch)))}
  return text
end
4

1 回答 1

2

在对 Rails 的正则表达式和字符串扫描进行了一些研究之后,我想出了我的问题的答案。这是我现在使用的方法的代码:

def replace_slugs(text, characters)
  # Regexp that will recognize wiki urls with pipes and return 2 items
  # It also ignores wiki urls that don't have a pipe
  # /\[\[:([^|\]]*)?\|([^\]]+)\]\]/
  links = text.scan(/\[\[:([^|\]]*)?\|([^\]]+)\]\]/)
  for link in links do
    slug = link[0]
    title = link[1]

    # I'm stripping out the whitespace when I do my find and for my link
    # This makes it so you can have whitespace before and after the pipe
    # e.g. [[:slug|Title]] [[:slug | Title]] [[:slug   |   Title]]
    ch = characters.find_by_slug(slug.strip)
    text.gsub!("[[:#{slug}|#{title}]]", link_to(title.strip,
      adventure_character_path(ch.adventure, ch))) if ch
  end

  slugs = text.scan(/\[{2}:([^\]]*)\]{2}/).map{|s|s[0]}
  characters.where(:slug => slugs).each{|ch| text.gsub!("[[:#{ch.slug}]]",
    link_to(ch.name, adventure_character_path(ch.adventure, ch)))}
  return text
end

Because of the way I formulated the regexp, I had to make two separate calls for when there are both links of form [[:slug]] and [[:slug|Title]]. Because of that, I've added an extra variable in the method called characters. This is so I can pass in an array of characters from where I call the method instead of having to search the entire database as that could get expensive and I already know the list of characters I want to use.

于 2012-09-25T08:42:33.717 回答