Merge branch 'master' of github.com:sinatra/sinatra

This commit is contained in:
Konstantin Haase 2012-07-30 20:08:47 +02:00
commit 4d40a5e26c
21 changed files with 272 additions and 102 deletions

View File

@ -551,6 +551,15 @@ Las opciones <tt>:callback</tt> y <tt>:variable</tt> se pueden utilizar para dec
var resource = {"foo":"bar","baz":"qux"}; present(resource);
=== Plantillas WLang
Dependencias:: {wlang}[https://github.com/blambeau/wlang/]
Extensiones de Archivo:: <tt>.wlang</tt>
Ejemplo:: <tt>wlang :index, :locals => { :clave => 'valor' }</tt>
Como no vas a poder llamar a métodos de Ruby (excepto por +yield+) desde una
plantilla WLang, casi siempre vas a querer pasarle locales.
=== Plantillas Embebidas
get '/' do
@ -1349,10 +1358,10 @@ Podés acceder a estas opciones utilizando el método <tt>settings</tt>:
=== Configurando la Protección de Ataques
Sinatra usa {Rack::Protection}[https://github.com/rkh/rack-protection#readme]
para defender a tu aplicación de los ataques más comunes. Tenés que tener en
cuenta que como consecuencia de esto puede venir asociada una disminución del
rendimiento de tu aplicación. Si por este, o algún otro motivo, querés
desactivar está funcionalidad, podés hacerlo:
para defender a tu aplicación de los ataques más comunes. Si por algún motivo,
querés desactivar esta funcionalidad, podés hacerlo como se indica a
continuación (tené en cuenta que tu aplicación va a quedar expuesta a un
montón de vulnerabilidades bien conocidas):
disable :protection

View File

@ -1,5 +1,4 @@
= Sinatra
= Sinatra
<i>Attention : Ce document correspond à la traduction de la version anglaise et
il n'est peut être plus à jour.</i>

View File

@ -251,7 +251,7 @@ Use the <tt>:static_cache_control</tt> setting (see below) to add
== Views / Templates
Each template language is exposed as via its own rendering method. These
Each template language is exposed via its own rendering method. These
methods simply return a string:
get '/' do
@ -755,7 +755,7 @@ middleware of choice as you would any other middleware:
end
To improve security, the session data in the cookie is signed with a session
secret. A random secret is generate for you by Sinatra. However, since this
secret. A random secret is generated for you by Sinatra. However, since this
secret will change with every start of your application, you might want to
set the secret yourself, so all your application instances share it:
@ -882,15 +882,15 @@ creating your own wrapper:
This allows you to implement streaming APIs,
{Server Sent Events}[http://dev.w3.org/html5/eventsource/] and can be used as
basis for {WebSockets}[http://en.wikipedia.org/wiki/WebSocket]. It can also be
the basis for {WebSockets}[http://en.wikipedia.org/wiki/WebSocket]. It can also be
used to increase throughput if some but not all content depends on a slow
resource.
Note that the streaming behavior, especially the number of concurrent request,
Note that the streaming behavior, especially the number of concurrent requests,
highly depends on the web server used to serve the application. Some servers,
like WEBRick, might not even support streaming at all. If the server does not
support streaming, the body will be sent all at once after the block passed to
+stream+ finished executing. Streaming does not work at all with Shotgun.
+stream+ finishes executing. Streaming does not work at all with Shotgun.
If the optional parameter is set to +keep_open+, it will not call +close+ on
the stream object, allowing you to close it at any later point in the
@ -1012,7 +1012,7 @@ Or use a session:
Setting your headers correctly is the foundation for proper HTTP caching.
You can easily set the Cache-Control header with like this:
You can easily set the Cache-Control header like this:
get '/' do
cache_control :public
@ -1033,7 +1033,7 @@ If you are using the +expires+ helper to set the corresponding header,
end
To properly use caches, you should consider using +etag+ or +last_modified+.
It is recommended to call those helpers *before* doing heavy lifting, as they
It is recommended to call those helpers *before* doing any heavy lifting, as they
will immediately flush a response if the client already has the current
version in its cache:
@ -1092,7 +1092,7 @@ For sending files, you can use the <tt>send_file</tt> helper method:
send_file 'foo.png'
end
It also takes a couple of options:
It also takes options:
send_file 'foo.png', :type => :jpg
@ -1193,8 +1193,8 @@ You can also pass it a file name:
=== Dealing with Date and Time
Sinatra offers a +time_for+ helper method, which, from the given value
generates a Time object. It is also able to convert +DateTime+, +Date+ and
Sinatra offers a +time_for+ helper method that generates a Time object
from the given value. It is also able to convert +DateTime+, +Date+ and
similar classes:
get '/' do
@ -1315,7 +1315,7 @@ You can access those options via <tt>settings</tt>:
Sinatra is using
{Rack::Protection}[https://github.com/rkh/rack-protection#readme] to defend
you application against common, opportunistic attacks. You can easily disable
this behavior (which will open your application to tons of common
this behavior (which will open up your application to tons of common
vulnerabilities):
disable :protection
@ -1337,7 +1337,7 @@ You can also hand in an array in order to disable a list of protections:
Enable if your app is running behind a reverse proxy that
has not been set up properly. Note that the +url+ helper
will still produce absolute URLs, unless you pass in
+false+ as second parameter.
+false+ as the second parameter.
Disabled per default.
@ -1410,16 +1410,19 @@ You can also hand in an array in order to disable a list of protections:
defaults to ['thin', 'mongrel', 'webrick'], order
indicates priority.
[sessions] enable cookie based sessions support using
[sessions] enable cookie-based sessions support using
<tt>Rack::Session::Cookie</tt>. See 'Using Sessions'
section for more information.
[show_exceptions] show a stack trace in the browser when an exception
happens. Enabled by default when <tt>environment</tt>
is set to <tt>"development"</tt>, disabled otherwise.
Can also be set to <tt>:after_handler</tt> to trigger
app-specified error handling before showing a stack
trace in the browser.
[static] Whether Sinatra should handle serving static files.
Disable when using a Server able to do this on its own.
Disable when using a server able to do this on its own.
Disabling will boost performance.
Enabled per default in classic style, disabled for
modular apps.
@ -1441,17 +1444,17 @@ You can also hand in an array in order to disable a list of protections:
There are three predefined +environments+: <tt>"development"</tt>,
<tt>"production"</tt> and <tt>"test"</tt>. Environments can be set
through the +RACK_ENV+ environment variable. The default value is
<tt>"development"</tt>. In this mode, all templates are reloaded between
requests. Special <tt>not_found</tt> and <tt>error</tt> handlers are installed
for this environment so you will see a stack trace in your browser.
In <tt>"production"</tt> and <tt>"test"</tt> templates are cached by default.
<tt>"development"</tt>. In the <tt>"development"</tt> environment all templates are reloaded between
requests, and special <tt>not_found</tt> and <tt>error</tt> handlers
display stack traces in your browser.
In the <tt>"production"</tt> and <tt>"test"</tt> environments, templates are cached by default.
To run different environments use the <tt>-e</tt> option:
ruby my_app.rb -e [ENVIRONMENT]
You can use predefined methods: +development?+, +test?+ and +production?+ to
check which enviroment is currently set.
check the current environment setting.
== Error Handling
@ -1608,7 +1611,7 @@ directories, logging, exception detail page, etc.). That's where
end
end
The methods available to <tt>Sinatra::Base</tt> subclasses are exactly as those
The methods available to <tt>Sinatra::Base</tt> subclasses are exactly the same as those
available via the top-level DSL. Most top-level apps can be converted to
<tt>Sinatra::Base</tt> components with two modifications:
@ -1625,13 +1628,13 @@ for details on available options and their behavior.
=== Modular vs. Classic Style
Contrary to common belief, there is nothing wrong with classic style. If it
Contrary to common belief, there is nothing wrong with the classic style. If it
suits your application, you do not have to switch to a modular application.
The main downsides of using classic style rather than modular style is that
you may only have one Sinatra application per Ruby process. If you plan to use
more than one, switch to modular style. There is no reason you cannot mix
modular and classic style.
The main disadvantage of using the classic style rather than the modular style is that
you will only have one Sinatra application per Ruby process. If you plan to use
more than one, switch to the modular style. There is no reason you cannot mix
the modular and the classic styles.
If switching from one style to the other, you should be aware of slightly
different default settings:
@ -1665,7 +1668,7 @@ Start with:
ruby my_app.rb
Or with a <tt>config.ru</tt>, which allows using any Rack handler:
Or with a <tt>config.ru</tt> file, which allows using any Rack handler:
# config.ru
require './my_app'
@ -1693,15 +1696,15 @@ And a corresponding <tt>config.ru</tt>:
=== When to use a config.ru?
Good signs you probably want to use a <tt>config.ru</tt>:
A <tt>config.ru</tt> file is recommended if:
* You want to deploy with a different Rack handler (Passenger, Unicorn,
Heroku, ...).
* You want to use more than one subclass of <tt>Sinatra::Base</tt>.
* You want to use Sinatra only for middleware, but not as endpoint.
* You want to use Sinatra only for middleware, and not as an endpoint.
<b>There is no need to switch to a <tt>config.ru</tt> only because you
switched to modular style, and you don't have to use modular style for running
<b>There is no need to switch to a <tt>config.ru</tt> simply because you
switched to the modular style, and you don't have to use the modular style for running
with a <tt>config.ru</tt>.</b>
=== Using Sinatra as Middleware
@ -1749,7 +1752,7 @@ assign them to a constant, you can do this with <tt>Sinatra.new</tt>:
my_app = Sinatra.new { get('/') { "hi" } }
my_app.run!
It takes the application to inherit from as optional argument:
It takes the application to inherit from as an optional argument:
# config.ru
require 'sinatra/base'
@ -1791,7 +1794,7 @@ Every Sinatra application corresponds to a subclass of <tt>Sinatra::Base</tt>.
If you are using the top-level DSL (<tt>require 'sinatra'</tt>), then this
class is <tt>Sinatra::Application</tt>, otherwise it is the subclass you
created explicitly. At class level you have methods like +get+ or +before+, but
you cannot access the +request+ object or the +session+, as there only is a
you cannot access the +request+ or +session+ objects, as there is only a
single application class for all requests.
Options created via +set+ are methods at class level:
@ -1817,13 +1820,13 @@ You have the application scope binding inside:
You can reach the scope object (the class) like this:
* Via the object passed to configure blocks (<tt>configure { |c| ... }</tt>)
* +settings+ from within request scope
* +settings+ from within the request scope
=== Request/Instance Scope
For every incoming request, a new instance of your application class is
created and all handler blocks run in that scope. From within this scope you
can access the +request+ and +session+ object or call rendering methods like
can access the +request+ and +session+ objects or call rendering methods like
+erb+ or +haml+. You can access the application scope from within the request
scope via the +settings+ helper:
@ -1852,8 +1855,8 @@ You have the request scope binding inside:
=== Delegation Scope
The delegation scope just forwards methods to the class scope. However, it
does not behave 100% like the class scope, as you do not have the class
binding. Only methods explicitly marked for delegation are available and you
does not behave exactly like the class scope, as you do not have the class
binding. Only methods explicitly marked for delegation are available, and you
do not share variables/state with the class scope (read: you have a different
+self+). You can explicitly add method delegations by calling
<tt>Sinatra::Delegator.delegate :method_name</tt>.
@ -1889,14 +1892,14 @@ The following Ruby versions are officially supported:
[ Ruby 1.8.7 ]
1.8.7 is fully supported, however, if nothing is keeping you from it, we
recommend upgrading to 1.9.2 or switching to JRuby or Rubinius. Support for
1.8.7 will not be dropped before Sinatra 2.0 and Ruby 2.0 except maybe for
1.8.7 will not be dropped before Sinatra 2.0 and Ruby 2.0 except maybe in
the unlikely event of 1.8.8 being released. Even then, we might continue
supporting it. <b>Ruby 1.8.6 is no longer supported.</b> If you want to run
with 1.8.6, downgrade to Sinatra 1.2, which will receive bug fixes until
Sinatra 1.4.0 is released.
[ Ruby 1.9.2 ]
1.9.2 is fully supported and recommended. Do not use 1.9.2p0, it is known to
1.9.2 is fully supported and recommended. Do not use 1.9.2p0, as it is known to
cause segmentation faults when running Sinatra. Support will continue at least
until the release of Ruby 1.9.4/2.0 and support for the latest 1.9 release
will continue as long as it is still supported by the Ruby core team.
@ -1906,8 +1909,8 @@ The following Ruby versions are officially supported:
from an earlier version will invalidate all sessions.
[ Rubinius ]
Rubinius is officially supported (Rubinius >= 1.2.4), everything, including
all template languages, works. The upcoming 2.0 release is supported as
Rubinius is officially supported (Rubinius >= 1.2.4), everything works, including
all template languages. The upcoming 2.0 release is supported as
well, including 1.9 mode.
[ JRuby ]
@ -1938,12 +1941,12 @@ both 1.9.4p0 and 2.0.0p0 to be supported.
Sinatra should work on any operating system supported by the chosen Ruby
implementation.
You will not be able to run Sinatra on Cardinal, SmallRuby, BlueRuby or any
Ruby version prior to 1.8.7 as of the time being.
Sinatra currently doesn't run on Cardinal, SmallRuby, BlueRuby or any
Ruby version prior to 1.8.7.
== The Bleeding Edge
If you would like to use Sinatra's latest bleeding code, feel free to run your
If you would like to use Sinatra's latest bleeding-edge code, feel free to run your
application against the master branch, it should be rather stable.
We also push out prerelease gems from time to time, so you can do a
@ -1970,7 +1973,7 @@ Then, in your project directory, create a +Gemfile+:
gem 'haml' # for instance, if you use haml
gem 'activerecord', '~> 3.0' # maybe you also need ActiveRecord 3.x
Note that you will have to list all your applications dependencies in there.
Note that you will have to list all your application's dependencies in the +Gemfile+.
Sinatra's direct dependencies (Rack and Tilt) will, however, be automatically
fetched and added by Bundler.

View File

@ -56,7 +56,7 @@ Thin — это более производительный и функцион
Маршруты сверяются с запросом в порядке очередности их записи в файле приложения.
Первый же совпавший с запросом маршрут и будет вызван.
Шаблоны маршрутов могут включать в себя именные параметры доступные
Шаблоны маршрутов могут включать в себя именованные параметры доступные
в xэше <tt>params</tt>:
get '/hello/:name' do
@ -65,7 +65,7 @@ Thin — это более производительный и функцион
"Hello #{params[:name]}!"
end
Также можно использовать именные параметры в качестве переменных
Также можно использовать именованные параметры в качестве переменных
блока:
get '/hello/:name' do |n|
@ -117,7 +117,7 @@ Thin — это более производительный и функцион
=== Условия
Маршруты могут включать различные условия совпадений, например,
клиентской приложение (user agent):
клиентское приложение (user agent):
get '/foo', :agent => /Songbird (\d\.\d)[\d\/]*?/ do
"You're using Songbird version #{params[:agent][0]}"
@ -544,6 +544,15 @@ Thin — это более производительный и функцион
var resource = {"foo":"bar","baz":"qux"}; present(resource);
=== WLang шаблоны
Зависимости:: {wlang}[https://github.com/blambeau/wlang/]
Расширения файлов:: <tt>.wlang</tt>
Пример:: <tt>wlang :index, :locals => { :key => 'value' }</tt>
Так как в WLang шаблонах невозможно вызывать методы из Ruby напрямую (за исключением +yield+), то
вы почти всегда будете передавать в шаблон локальные переменные.
=== Встроенные шаблоны
get '/' do
@ -594,7 +603,7 @@ Thin — это более производительный и функцион
загружены автоматически. Вызовите <tt>enable :inline_templates</tt> напрямую, если
используете вложенные шаблоны в других файлах.
=== Именные шаблоны
=== Именованные шаблоны
Шаблоны также могут быть определены при помощи <tt>template</tt> метода:
@ -1314,7 +1323,7 @@ Sinatra предлагает метод-помощник +time_for+, котор
Sinatra использует
{Rack::Protection}[https://github.com/rkh/rack-protection#readme] для
защиты приложения от простых атак. Вы можете легко выключить эту
защиту (что даст прирост в производительности):
защиту (что сделает ваше приложение чрезвычайно уязвимым):
disable :protection
@ -1411,6 +1420,9 @@ Sinatra использует
[show_exceptions] показывать исключения/стек вызовов (stack trace) в браузере.
По умолчанию включено только в окружении <tt>development</tt>.
Может быть установлено в <tt>:after_handler</tt> для запуска специфичной
для приложения обработки ошибок, прежде чем показывать трассировку
стека в браузере.
[static] должна ли Sinatra осуществлять раздачу статических файлов.
Отключите, когда используете какой-либо веб-сервер для этой цели.

View File

@ -25,11 +25,11 @@ __END__
@@ layout
<html>
<head>
<title>Super Simple Chat with Sinatra</title>
<head>
<title>Super Simple Chat with Sinatra</title>
<meta charset="utf-8" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
</head>
<body><%= yield %></body>
</html>
@ -58,4 +58,4 @@ __END__
<form>
<input id='msg' placeholder='type message here...' />
</form>
</form>

View File

@ -1,7 +1,7 @@
# external dependencies
require 'rack'
require 'tilt'
require "rack/protection"
require 'rack/protection'
# stdlib dependencies
require 'thread'
@ -1314,17 +1314,21 @@ module Sinatra
def compile(path)
keys = []
if path.respond_to? :to_str
pattern = path.to_str.gsub(/[^\?\%\\\/\:\*\w]/) { |c| encoded(c) }
ignore = ""
pattern = path.to_str.gsub(/[^\?\%\\\/\:\*\w]/) do |c|
ignore << escaped(c).join if c.match(/[\.@]/)
encoded(c)
end
pattern.gsub!(/((:\w+)|\*)/) do |match|
if match == "*"
keys << 'splat'
"(.*?)"
else
keys << $2[1..-1]
"([^/?#]+)"
"([^#{ignore}/?#]+)"
end
end
[/^#{pattern}$/, keys]
[/\A#{pattern}\z/, keys]
elsif path.respond_to?(:keys) && path.respond_to?(:match)
[path, path.keys]
elsif path.respond_to?(:names) && path.respond_to?(:match)
@ -1340,11 +1344,15 @@ module Sinatra
def encoded(char)
enc = URI.escape(char)
enc = "(?:#{Regexp.escape enc}|#{URI.escape char, /./})" if enc == char
enc = "(?:#{escaped(char, enc).join('|')})" if enc == char
enc = "(?:#{enc}|#{encoded('+')})" if char == " "
enc
end
def escaped(char, enc = URI.escape(char))
[Regexp.escape(enc), URI.escape(char, /./)]
end
public
# Makes the methods defined in the block and in the Modules given
# in `extensions` available to the handlers and templates

View File

@ -10,7 +10,7 @@ Gem::Specification.new 'sinatra', Sinatra::VERSION do |s|
s.files = `git ls-files`.split("\n") - %w[.gitignore .travis.yml]
s.test_files = s.files.select { |p| p =~ /^test\/.*_test.rb/ }
s.extra_rdoc_files = s.files.select { |p| p =~ /^README/ } << 'LICENSE'
s.rdoc_options = %w[--line-numbers --inline-source --title Sinatra --main README.rdoc]
s.rdoc_options = %w[--line-numbers --inline-source --title Sinatra --main README.rdoc --encoding=UTF-8]
s.add_dependency 'rack', '~> 1.3', '>= 1.3.6'
s.add_dependency 'rack-protection', '~> 1.2'

139
test/compile_test.rb Normal file
View File

@ -0,0 +1,139 @@
# I like coding: UTF-8
require File.expand_path('../helper', __FILE__)
class CompileTest < Test::Unit::TestCase
def self.converts pattern, expected_regexp
it "generates #{expected_regexp.source} from #{pattern}" do
compiled, _ = compiled pattern
assert_equal expected_regexp, compiled
end
end
def self.parses pattern, example, expected_params
it "parses #{example} with #{pattern} into params #{expected_params}" do
compiled, keys = compiled pattern
match = compiled.match(example)
fail %Q{"#{example}" does not parse on pattern "#{pattern}".} unless match
# Aggregate e.g. multiple splat values into one array.
#
params = keys.zip(match.captures).reduce({}) do |hash, mapping|
key, value = mapping
hash[key] = if existing = hash[key]
existing.respond_to?(:to_ary) ? existing << value : [existing, value]
else
value
end
hash
end
assert_equal(expected_params, params)
end
end
def self.fails pattern, example
it "does not parse #{example} with #{pattern}" do
compiled, _ = compiled pattern
match = compiled.match(example)
fail %Q{"#{pattern}" does parse "#{example}" but it should fail} if match
end
end
def compiled pattern
app ||= mock_app {}
compiled, keys = app.send(:compile, pattern)
[compiled, keys]
end
converts "/", %r{\A/\z}
parses "/", "/", {}
converts "/foo", %r{\A/foo\z}
parses "/foo", "/foo", {}
converts "/:foo", %r{\A/([^/?#]+)\z}
parses "/:foo", "/foo", "foo" => "foo"
parses "/:foo", "/foo.bar", "foo" => "foo.bar"
parses "/:foo", "/foo%2Fbar", "foo" => "foo%2Fbar"
fails "/:foo", "/foo?"
fails "/:foo", "/foo/bar"
fails "/:foo", "/"
fails "/:foo", "/foo/"
converts "/föö", %r{\A/f%C3%B6%C3%B6\z}
parses "/föö", "/f%C3%B6%C3%B6", {}
converts "/:foo/:bar", %r{\A/([^/?#]+)/([^/?#]+)\z}
parses "/:foo/:bar", "/foo/bar", "foo" => "foo", "bar" => "bar"
converts "/hello/:person", %r{\A/hello/([^/?#]+)\z}
parses "/hello/:person", "/hello/Frank", "person" => "Frank"
converts "/?:foo?/?:bar?", %r{\A/?([^/?#]+)?/?([^/?#]+)?\z}
parses "/?:foo?/?:bar?", "/hello/world", "foo" => "hello", "bar" => "world"
parses "/?:foo?/?:bar?", "/hello", "foo" => "hello", "bar" => nil
parses "/?:foo?/?:bar?", "/", "foo" => nil, "bar" => nil
parses "/?:foo?/?:bar?", "", "foo" => nil, "bar" => nil
converts "/*", %r{\A/(.*?)\z}
parses "/*", "/", "splat" => ""
parses "/*", "/foo", "splat" => "foo"
parses "/*", "/foo/bar", "splat" => "foo/bar"
converts "/:foo/*", %r{\A/([^/?#]+)/(.*?)\z}
parses "/:foo/*", "/foo/bar/baz", "foo" => "foo", "splat" => "bar/baz"
converts "/:foo/:bar", %r{\A/([^/?#]+)/([^/?#]+)\z}
parses "/:foo/:bar", "/user@example.com/name", "foo" => "user@example.com", "bar" => "name"
converts "/test$/", %r{\A/test(?:\$|%24)/\z}
parses "/test$/", "/test$/", {}
converts "/te+st/", %r{\A/te(?:\+|%2B)st/\z}
parses "/te+st/", "/te+st/", {}
fails "/te+st/", "/test/"
fails "/te+st/", "/teeest/"
converts "/test(bar)/", %r{\A/test(?:\(|%28)bar(?:\)|%29)/\z}
parses "/test(bar)/", "/test(bar)/", {}
converts "/path with spaces", %r{\A/path(?:%20|(?:\+|%2B))with(?:%20|(?:\+|%2B))spaces\z}
parses "/path with spaces", "/path%20with%20spaces", {}
parses "/path with spaces", "/path%2Bwith%2Bspaces", {}
parses "/path with spaces", "/path+with+spaces", {}
converts "/foo&bar", %r{\A/foo(?:&|%26)bar\z}
parses "/foo&bar", "/foo&bar", {}
converts "/:foo/*", %r{\A/([^/?#]+)/(.*?)\z}
parses "/:foo/*", "/hello%20world/how%20are%20you", "foo" => "hello%20world", "splat" => "how%20are%20you"
converts "/*/foo/*/*", %r{\A/(.*?)/foo/(.*?)/(.*?)\z}
parses "/*/foo/*/*", "/bar/foo/bling/baz/boom", "splat" => ["bar", "bling", "baz/boom"]
fails "/*/foo/*/*", "/bar/foo/baz"
converts "/test.bar", %r{\A/test(?:\.|%2E)bar\z}
parses "/test.bar", "/test.bar", {}
fails "/test.bar", "/test0bar"
converts "/:file.:ext", %r{\A/([^\.%2E/?#]+)(?:\.|%2E)([^\.%2E/?#]+)\z}
parses "/:file.:ext", "/pony.jpg", "file" => "pony", "ext" => "jpg"
parses "/:file.:ext", "/pony%2Ejpg", "file" => "pony", "ext" => "jpg"
fails "/:file.:ext", "/.jpg"
converts "/:name.?:format?", %r{\A/([^\.%2E/?#]+)(?:\.|%2E)?([^\.%2E/?#]+)?\z}
parses "/:name.?:format?", "/foo", "name" => "foo", "format" => nil
parses "/:name.?:format?", "/foo.bar", "name" => "foo", "format" => "bar"
parses "/:name.?:format?", "/foo%2Ebar", "name" => "foo", "format" => "bar"
fails "/:name.?:format?", "/.bar"
converts "/:user@?:host?", %r{\A/([^@%40/?#]+)(?:@|%40)?([^@%40/?#]+)?\z}
parses "/:user@?:host?", "/foo@bar", "user" => "foo", "host" => "bar"
parses "/:user@?:host?", "/foo.foo@bar", "user" => "foo.foo", "host" => "bar"
parses "/:user@?:host?", "/foo@bar.bar", "user" => "foo", "host" => "bar.bar"
# From https://gist.github.com/2154980#gistcomment-169469.
#
# converts "/:name(.:format)?", %r{\A/([^\.%2E/?#]+)(?:\(|%28)(?:\.|%2E)([^\.%2E/?#]+)(?:\)|%29)?\z}
# parses "/:name(.:format)?", "/foo", "name" => "foo", "format" => nil
# parses "/:name(.:format)?", "/foo.bar", "name" => "foo", "format" => "bar"
fails "/:name(.:format)?", "/foo."
end

View File

@ -1,15 +1,15 @@
# Copyright (c) 2009 Damian Janowski and Michel Martens for Citrusbyte
#
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

View File

@ -586,21 +586,21 @@ class HelpersTest < Test::Unit::TestCase
end
end
end
it 'sets the Content-Type response header' do
attachment_app('test.xml')
get '/attachment'
assert_equal 'application/xml;charset=utf-8', response['Content-Type']
assert_equal '<sinatra></sinatra>', body
end
end
it 'sets the Content-Type response header without extname' do
attachment_app('test')
get '/attachment'
assert_equal 'text/html;charset=utf-8', response['Content-Type']
assert_equal '<sinatra></sinatra>', body
assert_equal '<sinatra></sinatra>', body
end
it 'sets the Content-Type response header with extname' do
mock_app do
get('/attachment') do
@ -612,9 +612,9 @@ class HelpersTest < Test::Unit::TestCase
get '/attachment'
assert_equal 'application/atom+xml', response['Content-Type']
assert_equal '<sinatra></sinatra>', body
assert_equal '<sinatra></sinatra>', body
end
end
describe 'send_file' do

View File

@ -44,7 +44,7 @@ class LiquidTest < Test::Unit::TestCase
mock_app { get('/') { liquid :no_such_template } }
assert_raise(Errno::ENOENT) { get('/') }
end
it "allows passing locals" do
liquid_app {
liquid '{{ value }}', :locals => { :value => 'foo' }

View File

@ -211,7 +211,7 @@ class MappedErrorTest < Test::Unit::TestCase
assert_equal 500, status
end
it "allows a stack of exception_handlers" do
it "allows a stack of exception_handlers" do
mock_app do
set :raise_errors, false
error(FirstError) { 'First!' }
@ -223,7 +223,7 @@ class MappedErrorTest < Test::Unit::TestCase
assert_equal 'Second!', body
end
it "allows an exception handler to pass control to the next exception handler" do
it "allows an exception handler to pass control to the next exception handler" do
mock_app do
set :raise_errors, false
error(500, FirstError) { 'First!' }

View File

@ -55,7 +55,7 @@ class MarkabyTest < Test::Unit::TestCase
assert_equal "<h1>THIS. IS. <em>SPARTA</em></h1>", body
end
it 'renders inline markaby blocks with file layouts' do
it 'renders inline markaby blocks with file layouts' do
markaby_app { markaby(:layout => :layout2) { text "Hello World" } }
assert ok?
assert_equal "<h1>Markaby Layout!</h1><p>Hello World</p>", body
@ -65,7 +65,7 @@ class MarkabyTest < Test::Unit::TestCase
mock_app { get('/') { markaby :no_such_template } }
assert_raise(Errno::ENOENT) { get('/') }
end
it "allows passing locals" do
markaby_app {
markaby 'text value', :locals => { :value => 'foo' }

View File

@ -34,7 +34,7 @@ class RablTest < Test::Unit::TestCase
assert ok?
assert_equal '{"openstruct":{"bar":"baz"}}', body
end
it "renders with file layouts" do
rabl_app {
@foo = OpenStruct.new(:bar => 'baz')
@ -43,14 +43,14 @@ class RablTest < Test::Unit::TestCase
assert ok?
assert_equal '{"qux":{"openstruct":{"bar":"baz"}}}', body
end
it "raises error if template not found" do
mock_app {
get('/') { rabl :no_such_template }
}
assert_raise(Errno::ENOENT) { get('/') }
end
it "passes rabl options to the rabl engine" do
mock_app do
get('/') do
@ -65,7 +65,7 @@ class RablTest < Test::Unit::TestCase
assert ok?
assert_body '<?xml version="1.0" encoding="UTF-8"?><openstruct><bar>baz</bar></openstruct>'
end
it "passes default rabl options to the rabl engine" do
mock_app do
set :rabl, :format => 'xml'
@ -81,7 +81,7 @@ class RablTest < Test::Unit::TestCase
assert ok?
assert_body '<?xml version="1.0" encoding="UTF-8"?><openstruct><bar>baz</bar></openstruct>'
end
end
rescue LoadError

View File

@ -44,7 +44,7 @@ class RadiusTest < Test::Unit::TestCase
mock_app { get('/') { radius :no_such_template } }
assert_raise(Errno::ENOENT) { get('/') }
end
it "allows passing locals" do
radius_app {
radius '<r:value />', :locals => { :value => 'foo' }

View File

@ -47,13 +47,13 @@ class RouteAddedHookTest < Test::Unit::TestCase
assert_equal [["GET", "/"], ["HEAD", "/"]],
RouteAddedTest.routes
end
it "should pass route blocks as an argument" do
mock_app(Class.new(Sinatra::Base)) do
register RouteAddedTest
get('/') {}
end
assert_kind_of Proc, RouteAddedTest.procs.first
assert_kind_of Proc, RouteAddedTest.procs.first
end
end

View File

@ -75,9 +75,9 @@ class ScssTest < Test::Unit::TestCase
mock_app do
set :scss, {:style => :compact} # default scss style is :nested
get('/') {
scss("#scss {\n background-color: white;\n color: black;\n}")
scss("#scss {\n background-color: white;\n color: black;\n}")
}
end
end
get '/'
assert ok?
assert_equal "#scss { background-color: white; color: black; }\n", body

View File

@ -5,7 +5,7 @@ class SinatraTest < Test::Unit::TestCase
app = Sinatra.new { get('/') { 'Hello World' } }
assert_same Sinatra::Base, app.superclass
end
it "responds to #template_cache" do
assert_kind_of Tilt::Cache, Sinatra::Base.new!.template_cache
end

View File

@ -17,13 +17,13 @@ class SlimTest < Test::Unit::TestCase
assert ok?
assert_equal "<h1>Hiya</h1>", body
end
it 'renders .slim files in views path' do
slim_app { slim :hello }
assert ok?
assert_equal "<h1>Hello From Slim</h1>", body
end
it "renders with inline layouts" do
mock_app do
layout { %(h1\n | THIS. IS. \n == yield.upcase ) }
@ -33,27 +33,27 @@ class SlimTest < Test::Unit::TestCase
assert ok?
assert_equal "<h1>THIS. IS. <EM>SPARTA</EM></h1>", body
end
it "renders with file layouts" do
slim_app { slim('| Hello World', :layout => :layout2) }
assert ok?
assert_equal "<h1>Slim Layout!</h1><p>Hello World</p>", body
end
it "raises error if template not found" do
mock_app { get('/') { slim(:no_such_template) } }
assert_raise(Errno::ENOENT) { get('/') }
end
HTML4_DOCTYPE = "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">"
it "passes slim options to the slim engine" do
mock_app { get('/') { slim("x foo='bar'", :attr_wrapper => "'") }}
get '/'
assert ok?
assert_body "<x foo='bar'></x>"
end
it "passes default slim options to the slim engine" do
mock_app do
set :slim, :attr_wrapper => "'"
@ -63,7 +63,7 @@ class SlimTest < Test::Unit::TestCase
assert ok?
assert_body "<x foo='bar'></x>"
end
it "merges the default slim options with the overrides and passes them to the slim engine" do
mock_app do
set :slim, :attr_wrapper => "'"

View File

@ -288,7 +288,7 @@ __END__
@@ foo
this is foo
@@ bar
@@ bar
There's a space after 'bar'!
@@ foo bar

View File

@ -50,7 +50,7 @@ class YajlTest < Test::Unit::TestCase
it 'decorates the json with a callback' do
yajl_app do
yajl(
'json = { :foo => "bar" }',
'json = { :foo => "bar" }',
{ :callback => 'baz' }
)
end