Mustermann::CompileError 在 URL

Mustermann::CompileError in URL

我有一个 Sinatra 支持的博客,方法如下:

module Tir
  module Blog
    class Article

      def url
        [Tir::Config.domain, meta('relative_path')].join
      end

    end
  end
end

在 Article 实例上调用它会输出文章的完整 URI,例如:

"http://example.com/2018/07/08/test-article"

神奇的 Mustermann 给我以下错误:

Mustermann::CompileError: capture name can't be empty: "/http://example.com/2018/07/08/test-article"

  1. 为什么要在字符串的开头插入正斜杠?
  2. 为什么生成的字符串甚至不是 Sinatra 路由的限制如此之大?
  3. 如何解决这个问题?

谢谢。

编辑 2018 年 8 月 29 日: 事实证明,Sinatra / Mustermann 阻止了这些字符串,因为它们 路由。我生成动态文章路由的主要方法是这样的:

articles = []

Dir.glob('articles/*.mdown') do |file|
 article = initialize_article file
 if article.ready?
   get("/#{article.url}") do
    erb :'articles/article',
    :locals => { :article => article },
    :layout => :'articles/layout_article'
   end
   articles << article
 end
end

改进版在get块中使用了不同的方法:

#articles.rb

articles = []

Dir.glob('articles/*.mdown') do |file|
 article = initialize_article file
 if article.ready?
   get("/#{article.relative_path}") do
    erb :'articles/article',
    :locals => { :article => article },
    :layout => :'articles/layout_article'
   end
   articles << article
 end
end

方法定义:

#blog.rb

def relative_path
 meta('relative_path')
end

def url
 [Tir::Config.domain, meta('relative_path')].join
end

所以现在 url 方法不会在路由中调用,只会在其中一个视图中的文章对象上调用 — 因此没有错误。

Sinatra 路由助手和 Mustermann 本身不接受完整的 URLs 作为模式,只接受路径 - 您不能将主机名放入其中。 Mustermann 的 README 提供了支持的模式类型的完整列表,并且那里的所有样本都显示了路径。正如您所称,'restrictive' 行为是正常的,因为它不是通用模式匹配库 - 它专门用于处理 URL 路径。

如果您不想为 Sinatra 路由指定主机名,您可以使用可选的 host_name 参数。

get '/2018/07/08/test-article', host_name: 'example.com' do
  erb :article  
end

如果您想使用 Mustermann 进行自定义匹配,文档中列出的 uri-template 模式类型适用于完整的 URLs。您将必须安装 mustermann-contrib gem 并掌握略有不同的模式语法。

irb(main):011:0> require 'mustermann'
=> true
irb(main):012:0> pattern = Mustermann.new("http://example.com/2018/07/08/{slug}", type: 'uri-template')
=> #<Mustermann::Template:"http://example.com/2018/07/08/{slug}">
irb(main):013:0> pattern.match "http://example.com/2018/07/08/test-article"
=> #<MatchData "http://example.com/2018/07/08/test-article" slug:"test-article">