如何在Rails中改进类似wiki的链接?

时间:2012-09-24 16:15:26

标签: ruby-on-rails regex

我有一个Rails应用程序,我正在进行文本编辑并允许类似wiki的链接。我已经能够使它工作,所以你可以在描述中编写[[:slug]],它将生成相关页面的链接,链接文本是保存在数据库中的名称。我想这样做,以便我可以写[[:slug |一些文字]]和链接会说“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

1 个答案:

答案 0 :(得分:2)

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

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

由于我制定正则表达式的方式,当有[[:slug]]和[[:slug | Title]]形式的链接时,我不得不进行两次单独的调用。因此,我在名为characters的方法中添加了一个额外的变量。这样我就可以从我调用方法的地方传入一个字符数组,而不必搜索整个数据库,因为这可能会变得昂贵而且我已经知道了我想要使用的字符列表。