sinatra 1.3.0.c → 1.3.0.d
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sinatra might be problematic. Click here for more details.
- data/CHANGES +32 -0
- data/Gemfile +7 -1
- data/LICENSE +1 -1
- data/README.de.rdoc +81 -73
- data/README.es.rdoc +26 -6
- data/README.fr.rdoc +17 -3
- data/README.hu.rdoc +1 -1
- data/README.jp.rdoc +14 -1
- data/README.pt-br.rdoc +1 -1
- data/README.pt-pt.rdoc +1 -1
- data/README.rdoc +145 -277
- data/README.ru.rdoc +16 -3
- data/README.zh.rdoc +16 -3
- data/lib/sinatra/base.rb +25 -30
- data/sinatra.gemspec +5 -7
- data/test/creole_test.rb +65 -0
- data/test/delegator_test.rb +27 -1
- data/test/erb_test.rb +24 -1
- data/test/helper.rb +7 -0
- data/test/helpers_test.rb +14 -0
- data/test/markdown_test.rb +54 -9
- data/test/radius_test.rb +0 -1
- data/test/rdoc_test.rb +30 -0
- data/test/routing_test.rb +35 -4
- data/test/settings_test.rb +18 -0
- data/test/textile_test.rb +30 -0
- data/test/views/hello.creole +1 -0
- metadata +8 -15
- data/test/erubis_test.rb +0 -88
- data/test/views/error.erubis +0 -3
- data/test/views/hello.erubis +0 -1
- data/test/views/layout2.erubis +0 -2
data/README.ru.rdoc
CHANGED
@@ -584,6 +584,19 @@ Thin - это более производительный и функциона
|
|
584
584
|
|
585
585
|
Отобразит <tt>./views/index.slim</tt>.
|
586
586
|
|
587
|
+
=== Creole шаблоны
|
588
|
+
|
589
|
+
<tt>creole</tt> gem/библиотека необходима для рендеринга creole шаблонов:
|
590
|
+
|
591
|
+
# Вам нужно будет подключить creole в приложении
|
592
|
+
require 'creole'
|
593
|
+
|
594
|
+
get '/' do
|
595
|
+
creole :index
|
596
|
+
end
|
597
|
+
|
598
|
+
Отобразит <tt>./views/index.creole</tt>.
|
599
|
+
|
587
600
|
=== CoffeeScript шаблоны
|
588
601
|
|
589
602
|
Вам понадобится <tt>coffee-script</tt> gem/библиотека и что-то <b>одно</b> из следующего списка,
|
@@ -858,8 +871,8 @@ Thin - это более производительный и функциона
|
|
858
871
|
вызова другого обработчика маршрута. В таком случае просто используйте +call+:
|
859
872
|
|
860
873
|
get '/foo' do
|
861
|
-
status, headers, body = call
|
862
|
-
[status, body.upcase]
|
874
|
+
status, headers, body = call env.merge("PATH_INFO" => '/bar')
|
875
|
+
[status, headers, body.map(&:upcase)]
|
863
876
|
end
|
864
877
|
|
865
878
|
get '/bar' do
|
@@ -1349,7 +1362,7 @@ Thin - это более производительный и функциона
|
|
1349
1362
|
Частные ошибки:
|
1350
1363
|
|
1351
1364
|
error MyCustomError do
|
1352
|
-
'So what happened was...' +
|
1365
|
+
'So what happened was...' + env['sinatra.error'].message
|
1353
1366
|
end
|
1354
1367
|
|
1355
1368
|
Тогда, если это произошло:
|
data/README.zh.rdoc
CHANGED
@@ -582,6 +582,19 @@ Rack body对象或者HTTP状态码:
|
|
582
582
|
|
583
583
|
渲染 <tt>./views/index.slim</tt>。
|
584
584
|
|
585
|
+
=== Creole 模板
|
586
|
+
|
587
|
+
需要引入 <tt>creole</tt> gem/library 来渲染 Creole 模板:
|
588
|
+
|
589
|
+
# 需要在你的应用中引入 creole
|
590
|
+
require 'creole'
|
591
|
+
|
592
|
+
get '/' do
|
593
|
+
creole :index
|
594
|
+
end
|
595
|
+
|
596
|
+
渲染 <tt>./views/index.creole</tt>。
|
597
|
+
|
585
598
|
=== CoffeeScript 模板
|
586
599
|
|
587
600
|
需要引入 <tt>coffee-script</tt> gem/library 并至少满足下面条件一项
|
@@ -843,8 +856,8 @@ Session被用来在请求之间保持状态。如果被激活,每一个用户
|
|
843
856
|
。简单的使用 +call+ 可以做到这一点:
|
844
857
|
|
845
858
|
get '/foo' do
|
846
|
-
status, headers, body = call
|
847
|
-
[status, body.upcase]
|
859
|
+
status, headers, body = call env.merge("PATH_INFO" => '/bar')
|
860
|
+
[status, headers, body.map(&:upcase)]
|
848
861
|
end
|
849
862
|
|
850
863
|
get '/bar' do
|
@@ -1314,7 +1327,7 @@ Sinatra会自动处理range请求。
|
|
1314
1327
|
自定义错误:
|
1315
1328
|
|
1316
1329
|
error MyCustomError do
|
1317
|
-
'So what happened was...' +
|
1330
|
+
'So what happened was...' + env['sinatra.error'].message
|
1318
1331
|
end
|
1319
1332
|
|
1320
1333
|
那么,当这个发生的时候:
|
data/lib/sinatra/base.rb
CHANGED
@@ -6,15 +6,11 @@ require 'sinatra/showexceptions'
|
|
6
6
|
require 'tilt'
|
7
7
|
|
8
8
|
module Sinatra
|
9
|
-
VERSION = '1.3.0.
|
9
|
+
VERSION = '1.3.0.d'
|
10
10
|
|
11
11
|
# The request object. See Rack::Request for more info:
|
12
12
|
# http://rack.rubyforge.org/doc/classes/Rack/Request.html
|
13
13
|
class Request < Rack::Request
|
14
|
-
def self.new(env)
|
15
|
-
env['sinatra.request'] ||= super
|
16
|
-
end
|
17
|
-
|
18
14
|
# Returns an array of acceptable media types for the response
|
19
15
|
def accept
|
20
16
|
@env['sinatra.accept'] ||= begin
|
@@ -366,7 +362,7 @@ module Sinatra
|
|
366
362
|
time = time_for time
|
367
363
|
response['Last-Modified'] = time.httpdate
|
368
364
|
# compare based on seconds since epoch
|
369
|
-
halt 304 if Time.httpdate(
|
365
|
+
halt 304 if Time.httpdate(env['HTTP_IF_MODIFIED_SINCE']).to_i >= time.to_i
|
370
366
|
rescue ArgumentError
|
371
367
|
end
|
372
368
|
|
@@ -455,6 +451,8 @@ module Sinatra
|
|
455
451
|
end
|
456
452
|
|
457
453
|
def erubis(template, options={}, locals={})
|
454
|
+
warn "Sinatra::Templates#erubis is deprecated and will be removed, use #erb instead.\n" \
|
455
|
+
"If you have Erubis installed, it will be used automatically.\n\tfrom #{caller.first}"
|
458
456
|
render :erubis, template, options, locals
|
459
457
|
end
|
460
458
|
|
@@ -520,12 +518,16 @@ module Sinatra
|
|
520
518
|
render :slim, template, options, locals
|
521
519
|
end
|
522
520
|
|
521
|
+
def creole(template, options={}, locals={})
|
522
|
+
render :creole, template, options, locals
|
523
|
+
end
|
524
|
+
|
523
525
|
# Calls the given block for every possible template file in views,
|
524
526
|
# named name.ext, where ext is registered on engine.
|
525
527
|
def find_template(views, name, engine)
|
526
528
|
yield ::File.join(views, "#{name}.#{@preferred_extension}")
|
527
529
|
Tilt.mappings.each do |ext, engines|
|
528
|
-
next unless ext != @preferred_extension and
|
530
|
+
next unless ext != @preferred_extension and engines.include? engine
|
529
531
|
yield ::File.join(views, "#{name}.#{ext}")
|
530
532
|
end
|
531
533
|
end
|
@@ -650,17 +652,7 @@ module Sinatra
|
|
650
652
|
end
|
651
653
|
end
|
652
654
|
|
653
|
-
|
654
|
-
|
655
|
-
# Never produce a body on HEAD requests. Do retain the Content-Length
|
656
|
-
# unless it's "0", in which case we assume it was calculated erroneously
|
657
|
-
# for a manual HEAD response and remove it entirely.
|
658
|
-
if @env['REQUEST_METHOD'] == 'HEAD'
|
659
|
-
body = []
|
660
|
-
header.delete('Content-Length') if header['Content-Length'] == '0'
|
661
|
-
end
|
662
|
-
|
663
|
-
[status, header, body]
|
655
|
+
@response.finish
|
664
656
|
end
|
665
657
|
|
666
658
|
# Access settings defined with Base.set.
|
@@ -696,7 +688,7 @@ module Sinatra
|
|
696
688
|
# Forward the request to the downstream app -- middleware only.
|
697
689
|
def forward
|
698
690
|
fail "downstream app not set" unless @app.respond_to? :call
|
699
|
-
status, headers, body = @app.call
|
691
|
+
status, headers, body = @app.call env
|
700
692
|
@response.status = status
|
701
693
|
@response.body = body
|
702
694
|
@response.headers.merge! headers
|
@@ -948,14 +940,15 @@ module Sinatra
|
|
948
940
|
|
949
941
|
# Sets an option to the given value. If the value is a proc,
|
950
942
|
# the proc will be called every time the option is accessed.
|
951
|
-
def set(option, value=
|
952
|
-
raise ArgumentError if block
|
943
|
+
def set(option, value = (not_set = true), &block)
|
944
|
+
raise ArgumentError if block and !not_set
|
953
945
|
value = block if block
|
954
946
|
if value.kind_of?(Proc)
|
955
947
|
metadef(option, &value)
|
956
948
|
metadef("#{option}?") { !!__send__(option) }
|
957
949
|
metadef("#{option}=") { |val| metadef(option, &Proc.new{val}) }
|
958
|
-
elsif
|
950
|
+
elsif not_set
|
951
|
+
raise ArgumentError unless option.respond_to?(:each)
|
959
952
|
option.each { |k,v| set(k, v) }
|
960
953
|
elsif respond_to?("#{option}=")
|
961
954
|
__send__ "#{option}=", value
|
@@ -1269,6 +1262,7 @@ module Sinatra
|
|
1269
1262
|
builder = Rack::Builder.new
|
1270
1263
|
builder.use Rack::MethodOverride if method_override?
|
1271
1264
|
builder.use ShowExceptions if show_exceptions?
|
1265
|
+
builder.use Rack::Head
|
1272
1266
|
setup_logging builder
|
1273
1267
|
setup_sessions builder
|
1274
1268
|
middleware.each { |c,a,b| builder.use(c, *a, &b) }
|
@@ -1296,7 +1290,8 @@ module Sinatra
|
|
1296
1290
|
|
1297
1291
|
def setup_sessions(builder)
|
1298
1292
|
return unless sessions?
|
1299
|
-
options = {
|
1293
|
+
options = {}
|
1294
|
+
options[:secret] = session_secret if session_secret?
|
1300
1295
|
options.merge! sessions.to_hash if sessions.respond_to? :to_hash
|
1301
1296
|
builder.use Rack::Session::Cookie, options
|
1302
1297
|
end
|
@@ -1451,7 +1446,7 @@ module Sinatra
|
|
1451
1446
|
</style>
|
1452
1447
|
</head>
|
1453
1448
|
<body>
|
1454
|
-
<h2>Sinatra doesn
|
1449
|
+
<h2>Sinatra doesn’t know this ditty.</h2>
|
1455
1450
|
<img src='#{uri "/__sinatra__/404.png"}'>
|
1456
1451
|
<div id="c">
|
1457
1452
|
Try this:
|
@@ -1475,6 +1470,7 @@ module Sinatra
|
|
1475
1470
|
set :logging, Proc.new { ! test? }
|
1476
1471
|
set :method_override, true
|
1477
1472
|
set :run, Proc.new { ! test? }
|
1473
|
+
set :session_secret, Proc.new { super() unless development? }
|
1478
1474
|
|
1479
1475
|
def self.register(*extensions, &block) #:nodoc:
|
1480
1476
|
added_methods = extensions.map {|m| m.public_instance_methods }.flatten
|
@@ -1489,12 +1485,11 @@ module Sinatra
|
|
1489
1485
|
module Delegator #:nodoc:
|
1490
1486
|
def self.delegate(*methods)
|
1491
1487
|
methods.each do |method_name|
|
1492
|
-
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
|
1497
|
-
RUBY
|
1488
|
+
define_method(method_name) do |*args, &block|
|
1489
|
+
return super(*args, &block) if respond_to? method_name
|
1490
|
+
Delegator.target.send(method_name, *args, &block)
|
1491
|
+
end
|
1492
|
+
private method_name
|
1498
1493
|
end
|
1499
1494
|
end
|
1500
1495
|
|
data/sinatra.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
4
|
|
5
5
|
s.name = 'sinatra'
|
6
|
-
s.version = '1.3.0.
|
7
|
-
s.date = '2011-04-
|
6
|
+
s.version = '1.3.0.d'
|
7
|
+
s.date = '2011-04-30'
|
8
8
|
|
9
9
|
s.description = "Classy web-development dressed in a DSL"
|
10
10
|
s.summary = "Classy web-development dressed in a DSL"
|
@@ -41,10 +41,10 @@ Gem::Specification.new do |s|
|
|
41
41
|
test/builder_test.rb
|
42
42
|
test/coffee_test.rb
|
43
43
|
test/contest.rb
|
44
|
+
test/creole_test.rb
|
44
45
|
test/delegator_test.rb
|
45
46
|
test/encoding_test.rb
|
46
47
|
test/erb_test.rb
|
47
|
-
test/erubis_test.rb
|
48
48
|
test/extensions_test.rb
|
49
49
|
test/filter_test.rb
|
50
50
|
test/haml_test.rb
|
@@ -80,15 +80,14 @@ Gem::Specification.new do |s|
|
|
80
80
|
test/views/calc.html.erb
|
81
81
|
test/views/error.builder
|
82
82
|
test/views/error.erb
|
83
|
-
test/views/error.erubis
|
84
83
|
test/views/error.haml
|
85
84
|
test/views/error.sass
|
86
85
|
test/views/explicitly_nested.str
|
87
86
|
test/views/foo/hello.test
|
88
87
|
test/views/hello.builder
|
89
88
|
test/views/hello.coffee
|
89
|
+
test/views/hello.creole
|
90
90
|
test/views/hello.erb
|
91
|
-
test/views/hello.erubis
|
92
91
|
test/views/hello.haml
|
93
92
|
test/views/hello.less
|
94
93
|
test/views/hello.liquid
|
@@ -105,7 +104,6 @@ Gem::Specification.new do |s|
|
|
105
104
|
test/views/hello.textile
|
106
105
|
test/views/layout2.builder
|
107
106
|
test/views/layout2.erb
|
108
|
-
test/views/layout2.erubis
|
109
107
|
test/views/layout2.haml
|
110
108
|
test/views/layout2.liquid
|
111
109
|
test/views/layout2.mab
|
@@ -123,7 +121,7 @@ Gem::Specification.new do |s|
|
|
123
121
|
|
124
122
|
s.extra_rdoc_files = %w[README.rdoc README.de.rdoc README.jp.rdoc README.fr.rdoc README.es.rdoc README.hu.rdoc README.zh.rdoc LICENSE]
|
125
123
|
s.add_dependency 'rack', '~> 1.2'
|
126
|
-
s.add_dependency 'tilt', '~> 1.
|
124
|
+
s.add_dependency 'tilt', '~> 1.3'
|
127
125
|
s.add_development_dependency 'shotgun', '~> 0.6'
|
128
126
|
|
129
127
|
s.homepage = "http://sinatra.rubyforge.org"
|
data/test/creole_test.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/helper'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'creole'
|
5
|
+
|
6
|
+
class CreoleTest < Test::Unit::TestCase
|
7
|
+
def creole_app(&block)
|
8
|
+
mock_app do
|
9
|
+
set :views, File.dirname(__FILE__) + '/views'
|
10
|
+
get '/', &block
|
11
|
+
end
|
12
|
+
get '/'
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'renders inline creole strings' do
|
16
|
+
creole_app { creole '= Hiya' }
|
17
|
+
assert ok?
|
18
|
+
assert_body "<h1>Hiya</h1>"
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'renders .creole files in views path' do
|
22
|
+
creole_app { creole :hello }
|
23
|
+
assert ok?
|
24
|
+
assert_body "<h1>Hello From Creole</h1>"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "raises error if template not found" do
|
28
|
+
mock_app { get('/') { creole :no_such_template } }
|
29
|
+
assert_raise(Errno::ENOENT) { get('/') }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "renders with inline layouts" do
|
33
|
+
mock_app do
|
34
|
+
layout { 'THIS. IS. #{yield.upcase}!' }
|
35
|
+
get('/') { creole 'Sparta', :layout_engine => :str }
|
36
|
+
end
|
37
|
+
get '/'
|
38
|
+
assert ok?
|
39
|
+
assert_like 'THIS. IS. <P>SPARTA</P>!', body
|
40
|
+
end
|
41
|
+
|
42
|
+
it "renders with file layouts" do
|
43
|
+
creole_app { creole 'Hello World', :layout => :layout2, :layout_engine => :erb }
|
44
|
+
assert ok?
|
45
|
+
assert_body "ERB Layout!\n<p>Hello World</p>"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "can be used in a nested fashion for partials and whatnot" do
|
49
|
+
mock_app do
|
50
|
+
template(:inner) { "hi" }
|
51
|
+
template(:outer) { "<outer><%= creole :inner %></outer>" }
|
52
|
+
get '/' do
|
53
|
+
erb :outer
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
get '/'
|
58
|
+
assert ok?
|
59
|
+
assert_like '<outer><p>hi</p></outer>', body
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
rescue LoadError
|
64
|
+
warn "#{$!.to_s}: skipping creole tests"
|
65
|
+
end
|
data/test/delegator_test.rb
CHANGED
@@ -100,13 +100,39 @@ class DelegatorTest < Test::Unit::TestCase
|
|
100
100
|
assert_equal app.last_call, ["helpers", mixin.to_s ]
|
101
101
|
end
|
102
102
|
|
103
|
-
|
104
103
|
it "registers helpers with the delegation target" do
|
105
104
|
app, mixin = mirror, Module.new
|
106
105
|
Sinatra.use mixin
|
107
106
|
assert_equal app.last_call, ["use", mixin.to_s ]
|
108
107
|
end
|
109
108
|
|
109
|
+
it "should work with method_missing proxies for options" do
|
110
|
+
mixin = Module.new do
|
111
|
+
def respond_to?(method, *)
|
112
|
+
method.to_sym == :options or super
|
113
|
+
end
|
114
|
+
|
115
|
+
def method_missing(method, *args, &block)
|
116
|
+
return super unless method.to_sym == :options
|
117
|
+
{:some => :option}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
value = nil
|
122
|
+
mirror do
|
123
|
+
extend mixin
|
124
|
+
value = options
|
125
|
+
end
|
126
|
+
|
127
|
+
assert_equal({:some => :option}, value)
|
128
|
+
end
|
129
|
+
|
130
|
+
it "delegates crazy method names" do
|
131
|
+
Sinatra::Delegator.delegate "foo:bar:"
|
132
|
+
method = mirror { send "foo:bar:" }.last_call.first
|
133
|
+
assert_equal "foo:bar:", method
|
134
|
+
end
|
135
|
+
|
110
136
|
delegates 'get'
|
111
137
|
delegates 'patch'
|
112
138
|
delegates 'put'
|
data/test/erb_test.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
3
|
class ERBTest < Test::Unit::TestCase
|
4
|
+
def engine
|
5
|
+
Tilt::ERBTemplate
|
6
|
+
end
|
7
|
+
|
8
|
+
def setup
|
9
|
+
Tilt.prefer engine, :erb
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
4
13
|
def erb_app(&block)
|
5
14
|
mock_app {
|
6
15
|
set :views, File.dirname(__FILE__) + '/views'
|
@@ -9,6 +18,10 @@ class ERBTest < Test::Unit::TestCase
|
|
9
18
|
get '/'
|
10
19
|
end
|
11
20
|
|
21
|
+
it 'uses the correct engine' do
|
22
|
+
assert_equal engine, Tilt[:erb]
|
23
|
+
end
|
24
|
+
|
12
25
|
it 'renders inline ERB strings' do
|
13
26
|
erb_app { erb '<%= 1 + 1 %>' }
|
14
27
|
assert ok?
|
@@ -45,7 +58,7 @@ class ERBTest < Test::Unit::TestCase
|
|
45
58
|
erb 'Hello World', :layout => :layout2
|
46
59
|
}
|
47
60
|
assert ok?
|
48
|
-
|
61
|
+
assert_body "ERB Layout!\nHello World"
|
49
62
|
end
|
50
63
|
|
51
64
|
it "renders erb with blocks" do
|
@@ -79,3 +92,13 @@ class ERBTest < Test::Unit::TestCase
|
|
79
92
|
assert_equal '<outer><inner>hi</inner></outer>', body
|
80
93
|
end
|
81
94
|
end
|
95
|
+
|
96
|
+
|
97
|
+
begin
|
98
|
+
require 'erubis'
|
99
|
+
class ErubisTest < ERBTest
|
100
|
+
def engine; Tilt::ErubisTemplate end
|
101
|
+
end
|
102
|
+
rescue LoadError
|
103
|
+
warn "#{$!.to_s}: skipping erubis tests"
|
104
|
+
end
|
data/test/helper.rb
CHANGED
@@ -65,6 +65,11 @@ class Test::Unit::TestCase
|
|
65
65
|
assert_equal value.lstrip.gsub(/\s*\n\s*/, ""), body.lstrip.gsub(/\s*\n\s*/, "")
|
66
66
|
end
|
67
67
|
|
68
|
+
def assert_like(a,b)
|
69
|
+
pattern = /\s*\n\s*| id=['"][^"']*["']/
|
70
|
+
assert_equal a.strip.gsub(pattern, ""), b.strip.gsub(pattern, "")
|
71
|
+
end
|
72
|
+
|
68
73
|
def assert_include(str, substr)
|
69
74
|
assert str.include?(substr), "expected #{str.inspect} to include #{substr.inspect}"
|
70
75
|
end
|
@@ -76,6 +81,8 @@ class Test::Unit::TestCase
|
|
76
81
|
else
|
77
82
|
super
|
78
83
|
end
|
84
|
+
rescue Rack::Test::Error
|
85
|
+
super
|
79
86
|
end
|
80
87
|
|
81
88
|
# Also check response since we delegate there.
|