Sinatra 0.9.0 新特性

作者:Ryan Tomayko,2009 年 1 月 18 日,星期日

这是 0.9.x 版本系列中的第一个版本,旨在将 Sinatra 推向一个稳定的 1.0 版本。虽然我们在这次发布中添加了一些新特性,但主要重点是为未来的开发做好代码库的准备。在此过程中,许多长期存在的错误和轻微的烦恼都得到了修正。

在本版本中,Sinatra 的内部类和方法发生了重大变化。大多数为 0.3.x 编写的应用程序在新的代码库下可以正常工作,但我们已经开始添加弃用警告,这些警告将在 1.0 中完全删除。请在将生产环境升级到 0.9.0 gem 之前测试您的应用程序。我们致力于通过 0.9.x 保持现有应用程序的运行,因此请通过正常渠道报告兼容性问题。

言归正传,以下是一些 0.9.0 中值得关注的新特性。

Sinatra::Base 和正确的 Rack 身份

Sinatra 现在可以用来构建模块化/可重用的Rack 应用程序和中间件组件。这意味着多个 Sinatra 应用程序现在可以独立运行,并与其他基于 Rack 的框架和平共处。

要求'sinatra/base' 而不是'sinatra' 会导致 Sinatra 的一部分功能被加载。不会向顶层添加任何方法,并且命令行/自动运行功能会被禁用。子类化Sinatra::Base 会创建一个 Rack 组件,在类范围内可以使用熟悉的 Sinatra DSL 方法。然后,这些类可以作为 Rack 应用程序运行,也可以用作中间件组件。

此功能的完整文档正在制作中,但这里有一个简单的示例来说明

require 'sinatra/base'

class Foo < Sinatra::Base
  # all options are available for the setting:
  enable :static, :session
  set :root, File.dirname(__FILE__)

  # each subclass has its own private middleware stack:
  use Rack::Deflator

  # instance methods are helper methods and are available from
  # within filters, routes, and views:
  def em(text)
    "<em>#{text}</em>"
  end

  # routes are defined as usual:
  get '/hello/:person' do
    "Hello " + em(params[:person])
  end
end

这个东西可以插入 Rack 管道中的任何位置。例如,一旦 Rails 2.3 发布,你就可以使用 Sinatra 应用程序来构建Rails Metal

Jesse Newland 和 Jon Crosby 已经开始尝试。非常棒。

嵌套参数

带有下标的表单参数现在会被解析成一个嵌套/递归的 Hash 结构。这是一个表单

<form method='POST' action='/guestbook/'>
  <input type='text' name='person[name]'>
  <input type='text' name='person[email]'>
  <textarea name='note'></textarea>
</form>

它在网络上看起来像这样

person[name]=Frank&person[email][email protected]&message=Stay%20cool

Sinatra 通过 params 方法访问时,将其转换为嵌套的 Hash 结构

post '/guestbook/' do
  params[:person]    # => { :name => 'Frank', :email => '[email protected]' }
  "Hi #{person[:name]}! Thanks for signing my guestbook."
end

这是一个非常受欢迎的功能请求。感谢 Nicolás Sanguinetti 的补丁和 Michael Fellinger 的原始实现。

使用正则表达式路由

路由声明方法(getputpostputdelete)现在接受 Regexp 作为模式。捕获在 params[:captures] 中对路由块可用

get %r{/foo/(bar|baz)/(\d+)} do
  # assuming: GET /foo/bar/42
  params[:captures]  # => ['bar', 42]
end

传递路由

我们添加了一个新的请求级 pass 方法,它立即退出当前块并将控制权传递给下一个匹配的路由。例如

get '/shoot/:person' do
  pass unless %w[Kenny Sherrif].include?(params[:person])
  "You shot #{params[:person]}."
end

get '/shoot/*' do
  "Missed!"
end

如果在 pass 之后没有找到匹配的路由,则会引发 NotFound 异常,并且应用程序会返回 404,就像一开始没有匹配到任何路由一样。

改进的测试框架

Sinatra 的测试支持不再依赖于 Test::Unit(或任何特定的测试框架)。要求 'sinatra/test' 会引入 Sinatra::Test 模块Sinatra::TestHarness,这些模块和类可以根据需要用于模拟请求并对响应进行断言。

您还可以要求 sinatra/test/unitsinatra/test/specsinatra/test/rspecsinatra/test/bacon 来设置特定于框架的测试环境。有关示例,请参阅 README 中的“测试”部分。

更多

有关增强功能、错误修复和弃用功能的完整列表,请参阅 CHANGES 文件。