如何测试一个路由在Sinatra中是否有参数?



在Sinatra应用中,我有很多使用日期的路由。它们都是格式化的:

get '/foo/:bar/:year/:month' do
# code
end

我想创建一个before钩子,根据路由参数设置请求的日期。如果路由没有monthyear参数,则不应该运行。

我试过了:

before do
if params[:year].any? && params[:month].any?
@requested_date = Date.new(params[:year].to_i, params[:month].to_i, 01)
end
end

:

before do
if defined?(params[:year]) && defined?(params[:month])
@requested_date = Date.new(params[:year].to_i, params[:month].to_i, 01)
end
end

但是我一直遇到同样的错误:Date::Error - invalid date:

要可靠地检查params哈希是否有年/月键,您可以使用哈希#键?, smth。如:

before do
if params.key?(:year) && params.key?(:month)
<set date>
end
end

但是仍然有一个问题。路由'/foo/:bar/:year/:month'将匹配像/foo/bar/baz/qux这样的东西,Sinatra路由器将参数解析为{ bar: 'bar', year: 'baz', month: 'qux'}

因此,您仍然不能仅仅将参数提供给Date构造函数并期望它为您提供有效的日期。在最简单的情况下,您可以编写像

这样的辅助方法
def build_date(year, month)
Date.new(year.to_i, month.to_i, 01)
rescue Date::Error
# So what now?
end

并在before块中使用它,但是另一个问题出现了——如果出现错误该怎么办?最简单的解决方案是只响应404,但您可能需要更复杂的方法(例如,向用户传达无效的日期格式)。

另外要提到的是Sinatra使用regexp匹配路由的能力:例如,你可以强制Sinatra路由器只识别包含4个数字的年份和1-12范围内的整数的月份。我可能会避免它(使路由更难推理,访问匹配的参数也变得有点混乱),但仍然是一件值得记住的事情…

最新更新