sinatra 0.9.0.5 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sinatra might be problematic. Click here for more details.

@@ -9,7 +9,7 @@ require 'sinatra/base'
9
9
  require 'sinatra/main'
10
10
 
11
11
  # Like Kernel#warn but outputs the location that triggered the warning.
12
- def sinatra_warn(*message)
12
+ def sinatra_warn(*message) #:nodoc:
13
13
  line = caller.
14
14
  detect { |line| line !~ /(?:lib\/sinatra\/|__DELEGATE__)/ }.
15
15
  sub(/:in .*/, '')
@@ -34,25 +34,27 @@ end
34
34
  # technically a Sinatra issue but many Sinatra apps access the old
35
35
  # MIME_TYPES constants due to Sinatra example code.
36
36
  require 'rack/file'
37
- class Rack::File
38
- def self.const_missing(const_name)
39
- if const_name == :MIME_TYPES
40
- hash = Hash.new { |hash,key| Rack::Mime::MIME_TYPES[".#{key}"] }
41
- const_set :MIME_TYPES, hash
42
- sinatra_warn 'Rack::File::MIME_TYPES is deprecated; use Rack::Mime instead.'
43
- hash
44
- else
45
- super
37
+ module Rack #:nodoc:
38
+ class File #:nodoc:
39
+ def self.const_missing(const_name)
40
+ if const_name == :MIME_TYPES
41
+ hash = Hash.new { |hash,key| Rack::Mime::MIME_TYPES[".#{key}"] }
42
+ const_set :MIME_TYPES, hash
43
+ sinatra_warn 'Rack::File::MIME_TYPES is deprecated; use Rack::Mime instead.'
44
+ hash
45
+ else
46
+ super
47
+ end
46
48
  end
47
49
  end
48
50
  end
49
51
 
50
52
  module Sinatra
51
- module Compat
53
+ module Compat #:nodoc:
52
54
  end
53
55
 
54
56
  # Make Sinatra::EventContext an alias for Sinatra::Default to unbreak plugins.
55
- def self.const_missing(const_name)
57
+ def self.const_missing(const_name) #:nodoc:
56
58
  if const_name == :EventContext
57
59
  const_set :EventContext, Sinatra::Default
58
60
  sinatra_warn 'Sinatra::EventContext is deprecated; use Sinatra::Default instead.'
@@ -73,7 +75,7 @@ module Sinatra
73
75
  end
74
76
 
75
77
  class Default < Base
76
- def self.const_missing(const_name)
78
+ def self.const_missing(const_name) #:nodoc:
77
79
  if const_name == :FORWARD_METHODS
78
80
  sinatra_warn 'Sinatra::Application::FORWARD_METHODS is deprecated;',
79
81
  'use Sinatra::Delegator::METHODS instead.'
@@ -85,12 +87,10 @@ module Sinatra
85
87
  end
86
88
 
87
89
  # Deprecated. Use: response['Header-Name']
88
- def headers(header=nil)
89
- sinatra_warn "The 'headers' method is deprecated; use 'response' instead."
90
- response.headers.merge!(header) if header
91
- response.headers
90
+ def header(header=nil)
91
+ sinatra_warn "The 'header' method is deprecated; use 'headers' instead."
92
+ headers(header)
92
93
  end
93
- alias :header :headers
94
94
 
95
95
  # Deprecated. Use: halt
96
96
  def stop(*args, &block)
@@ -104,21 +104,21 @@ module Sinatra
104
104
  etag(*args, &block)
105
105
  end
106
106
 
107
- # The :disposition option is deprecated; use: #attachment. This method
108
- # setting the Content-Transfer-Encoding header is deprecated.
109
- #--
110
- # TODO deprecation warning for :disposition argument.
111
- def send_file(path, opts={})
112
- opts[:disposition] = 'attachment' if !opts.key?(:disposition)
113
- attachment opts[:filename] || path if opts[:filename] || opts[:disposition]
114
- response['Content-Transfer-Encoding'] = 'binary' if opts[:disposition]
115
- super(path, opts)
107
+ # Deprecated. Use the #attachment helper and return the data as a String or
108
+ # Array.
109
+ def send_data(data, options={})
110
+ sinatra_warn "The 'send_data' method is deprecated. use attachment, status, content_type, etc. helpers instead."
111
+
112
+ status options[:status] if options[:status]
113
+ attachment options[:filename] if options[:disposition] == 'attachment'
114
+ content_type options[:type] if options[:type]
115
+ halt data
116
116
  end
117
117
 
118
118
  # Throwing halt with a Symbol and the to_result convention are
119
119
  # deprecated. Override the invoke method to detect those types of return
120
120
  # values.
121
- def invoke(&block)
121
+ def invoke(&block) #:nodoc:
122
122
  res = super
123
123
  case
124
124
  when res.kind_of?(Symbol)
@@ -132,7 +132,7 @@ module Sinatra
132
132
  res
133
133
  end
134
134
 
135
- def options
135
+ def options #:nodoc:
136
136
  Options.new(self.class)
137
137
  end
138
138
 
@@ -195,7 +195,7 @@ module Sinatra
195
195
  end
196
196
 
197
197
  # Deprecated. Missing messages are no longer delegated to @response.
198
- def method_missing(name, *args, &b)
198
+ def method_missing(name, *args, &b) #:nodoc:
199
199
  if @response.respond_to?(name)
200
200
  sinatra_warn "The '#{name}' method is deprecated; use 'response.#{name}' instead."
201
201
  @response.send(name, *args, &b)
data/lib/sinatra/main.rb CHANGED
@@ -2,6 +2,10 @@ require 'sinatra/base'
2
2
 
3
3
  module Sinatra
4
4
  class Default < Base
5
+
6
+ # we assume that the first file that requires 'sinatra' is the
7
+ # app_file. all other path related options are calculated based
8
+ # on this path by default.
5
9
  set :app_file, lambda {
6
10
  ignore = [
7
11
  /lib\/sinatra.*\.rb$/, # all sinatra code
@@ -17,7 +21,6 @@ module Sinatra
17
21
  }.call
18
22
 
19
23
  set :run, Proc.new { $0 == app_file }
20
- set :reload, Proc.new{ app_file? && development? }
21
24
 
22
25
  if run? && ARGV.any?
23
26
  require 'optparse'
@@ -33,10 +36,6 @@ end
33
36
 
34
37
  include Sinatra::Delegator
35
38
 
36
- def helpers(&block)
37
- Sinatra::Application.send :class_eval, &block
38
- end
39
-
40
39
  def mime(ext, type)
41
40
  ext = ".#{ext}" unless ext.to_s[0] == ?.
42
41
  Rack::Mime::MIME_TYPES[ext.to_s] = type
@@ -1,6 +1,8 @@
1
1
  require 'bacon'
2
2
  require 'sinatra/test'
3
3
 
4
+ Sinatra::Test.deprecate('Bacon')
5
+
4
6
  Sinatra::Default.set(
5
7
  :environment => :test,
6
8
  :run => false,
@@ -3,6 +3,8 @@ require 'sinatra/test/unit'
3
3
  require 'spec'
4
4
  require 'spec/interop/test'
5
5
 
6
+ Sinatra::Test.deprecate('RSpec')
7
+
6
8
  Sinatra::Default.set(
7
9
  :environment => :test,
8
10
  :run => false,
@@ -2,6 +2,8 @@ require 'test/spec'
2
2
  require 'sinatra/test'
3
3
  require 'sinatra/test/unit'
4
4
 
5
+ Sinatra::Test.deprecate('test/spec')
6
+
5
7
  module Sinatra::Test
6
8
  def should
7
9
  @response.should
@@ -1,6 +1,8 @@
1
1
  require 'sinatra/test'
2
2
  require 'test/unit'
3
3
 
4
+ Sinatra::Test.deprecate('test/unit')
5
+
4
6
  Test::Unit::TestCase.send :include, Sinatra::Test
5
7
 
6
8
  Sinatra::Default.set(
data/lib/sinatra/test.rb CHANGED
@@ -1,51 +1,54 @@
1
1
  require 'sinatra/base'
2
2
 
3
3
  module Sinatra
4
-
5
4
  module Test
6
5
  include Rack::Utils
7
6
 
7
+ def self.included(base)
8
+ Sinatra::Default.set(:environment, :test)
9
+ end
10
+
8
11
  attr_reader :app, :request, :response
9
12
 
10
- def test_request(verb, path, *args)
13
+ def self.deprecate(framework)
14
+ warn <<-EOF
15
+ Warning: support for the #{framework} testing framework is deprecated and
16
+ will be dropped in Sinatra 1.0. See <http://sinatra.github.com/testing.html>
17
+ for more information.
18
+ EOF
19
+ end
20
+
21
+ def make_request(verb, path, body=nil, options={})
11
22
  @app = Sinatra::Application if @app.nil? && defined?(Sinatra::Application)
12
23
  fail "@app not set - cannot make request" if @app.nil?
24
+
13
25
  @request = Rack::MockRequest.new(@app)
14
- opts, input =
15
- case args.size
16
- when 2 # input, env
17
- input, env = args
18
- if input.kind_of?(Hash) # params, env
19
- [env, param_string(input)]
20
- else
21
- [env, input]
22
- end
23
- when 1 # params
24
- if (data = args.first).kind_of?(Hash)
25
- env = (data.delete(:env) || {})
26
- [env, param_string(data)]
27
- else
28
- [{}, data]
29
- end
30
- when 0
31
- [{}, '']
32
- else
33
- raise ArgumentError, "zero, one, or two arguments expected"
34
- end
35
- opts = rack_opts(opts)
36
- opts[:input] ||= input
26
+ options = { :lint => true }.merge(options || {})
27
+
28
+ case
29
+ when body.respond_to?(:to_hash)
30
+ options.merge! body.delete(:env) if body.key?(:env)
31
+ options[:input] = param_string(body)
32
+ when body.respond_to?(:to_str)
33
+ options[:input] = body
34
+ when body.nil?
35
+ options[:input] = ''
36
+ else
37
+ raise ArgumentError, "body must be a Hash, String, or nil"
38
+ end
39
+
37
40
  yield @request if block_given?
38
- @response = @request.request(verb, path, opts)
41
+ @response = @request.request(verb, path, rack_options(options))
39
42
  end
40
43
 
41
- def get(path, *args, &b) ; test_request('GET', path, *args, &b) ; end
42
- def head(path, *args, &b) ; test_request('HEAD', path, *args, &b) ; end
43
- def post(path, *args, &b) ; test_request('POST', path, *args, &b) ; end
44
- def put(path, *args, &b) ; test_request('PUT', path, *args, &b) ; end
45
- def delete(path, *args, &b) ; test_request('DELETE', path, *args, &b) ; end
44
+ def get(path, *args, &b) ; make_request('GET', path, *args, &b) ; end
45
+ def head(path, *args, &b) ; make_request('HEAD', path, *args, &b) ; end
46
+ def post(path, *args, &b) ; make_request('POST', path, *args, &b) ; end
47
+ def put(path, *args, &b) ; make_request('PUT', path, *args, &b) ; end
48
+ def delete(path, *args, &b) ; make_request('DELETE', path, *args, &b) ; end
46
49
 
47
50
  def follow!
48
- test_request 'GET', @response.location
51
+ make_request 'GET', @response.location
49
52
  end
50
53
 
51
54
  def body ; @response.body ; end
@@ -65,30 +68,38 @@ module Sinatra
65
68
  super || (@response && @response.respond_to?(symbol, include_private))
66
69
  end
67
70
 
68
- RACK_OPT_NAMES = {
69
- :accept => "HTTP_ACCEPT",
70
- :agent => "HTTP_USER_AGENT",
71
- :host => "HTTP_HOST",
72
- :session => "HTTP_COOKIE",
73
- :cookies => "HTTP_COOKIE",
74
- :content_type => "CONTENT_TYPE"
71
+ private
72
+
73
+ RACK_OPTIONS = {
74
+ :accept => 'HTTP_ACCEPT',
75
+ :agent => 'HTTP_USER_AGENT',
76
+ :host => 'HTTP_HOST',
77
+ :session => 'rack.session',
78
+ :cookies => 'HTTP_COOKIE',
79
+ :content_type => 'CONTENT_TYPE'
75
80
  }
76
81
 
77
- def rack_opts(opts)
78
- opts.inject({}) do |hash,(key,val)|
79
- key = RACK_OPT_NAMES[key] || key
82
+ def rack_options(opts)
83
+ opts.merge(:lint => true).inject({}) do |hash,(key,val)|
84
+ key = RACK_OPTIONS[key] || key
80
85
  hash[key] = val
81
86
  hash
82
87
  end
83
88
  end
84
89
 
85
- def env_for(opts={})
86
- opts = rack_opts(opts)
87
- Rack::MockRequest.env_for(opts)
88
- end
89
-
90
- def param_string(hash)
91
- hash.map { |pair| pair.map{|v|escape(v)}.join('=') }.join('&')
90
+ def param_string(value, prefix = nil)
91
+ case value
92
+ when Array
93
+ value.map { |v|
94
+ param_string(v, "#{prefix}[]")
95
+ } * "&"
96
+ when Hash
97
+ value.map { |k, v|
98
+ param_string(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
99
+ } * "&"
100
+ else
101
+ "#{prefix}=#{escape(value)}"
102
+ end
92
103
  end
93
104
 
94
105
  if defined? Sinatra::Compat
@@ -97,7 +108,7 @@ module Sinatra
97
108
  eval <<-RUBY, binding, __FILE__, __LINE__
98
109
  def #{verb}_it(*args, &block)
99
110
  sinatra_warn "The #{verb}_it method is deprecated; use #{verb} instead."
100
- test_request('#{verb.upcase}', *args, &block)
111
+ make_request('#{verb.upcase}', *args, &block)
101
112
  end
102
113
  RUBY
103
114
  end
@@ -109,6 +120,7 @@ module Sinatra
109
120
 
110
121
  def initialize(app=nil)
111
122
  @app = app || Sinatra::Application
123
+ @app.set(:environment, :test)
112
124
  end
113
125
  end
114
126
  end
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 = '0.9.0.5'
7
- s.date = '2009-03-09'
6
+ s.version = '0.9.1'
7
+ s.date = '2009-03-02'
8
8
 
9
9
  s.description = "Classy web-development dressed in a DSL"
10
10
  s.summary = "Classy web-development dressed in a DSL"
@@ -70,6 +70,7 @@ Gem::Specification.new do |s|
70
70
  test/builder_test.rb
71
71
  test/data/reload_app_file.rb
72
72
  test/erb_test.rb
73
+ test/extensions_test.rb
73
74
  test/filter_test.rb
74
75
  test/haml_test.rb
75
76
  test/helper.rb
@@ -79,12 +80,15 @@ Gem::Specification.new do |s|
79
80
  test/options_test.rb
80
81
  test/reload_test.rb
81
82
  test/request_test.rb
83
+ test/response_test.rb
82
84
  test/result_test.rb
83
85
  test/routing_test.rb
84
86
  test/sass_test.rb
87
+ test/server_test.rb
85
88
  test/sinatra_test.rb
86
89
  test/static_test.rb
87
90
  test/templates_test.rb
91
+ test/test_test.rb
88
92
  test/views/hello.builder
89
93
  test/views/hello.erb
90
94
  test/views/hello.haml
@@ -100,7 +104,7 @@ Gem::Specification.new do |s|
100
104
  s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/}
101
105
 
102
106
  s.extra_rdoc_files = %w[README.rdoc LICENSE]
103
- s.add_dependency 'rack', '>= 0.9.1'
107
+ s.add_dependency 'rack', '>= 0.9.1', '< 1.0'
104
108
 
105
109
  s.has_rdoc = true
106
110
  s.homepage = "http://sinatra.rubyforge.org"
data/test/base_test.rb CHANGED
@@ -1,68 +1,130 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
2
 
3
- describe 'Sinatra::Base' do
4
- it 'includes Rack::Utils' do
5
- assert Sinatra::Base.included_modules.include?(Rack::Utils)
3
+ describe 'Sinatra::Base subclasses' do
4
+
5
+ class TestApp < Sinatra::Base
6
+ get '/' do
7
+ 'Hello World'
8
+ end
9
+ end
10
+
11
+ it 'include Rack::Utils' do
12
+ assert TestApp.included_modules.include?(Rack::Utils)
6
13
  end
7
14
 
8
- it 'can be used as a Rack application' do
9
- mock_app {
10
- get '/' do
11
- 'Hello World'
12
- end
13
- }
14
- assert @app.respond_to?(:call)
15
+ it 'processes requests with #call' do
16
+ assert TestApp.respond_to?(:call)
15
17
 
16
- request = Rack::MockRequest.new(@app)
18
+ request = Rack::MockRequest.new(TestApp)
17
19
  response = request.get('/')
18
20
  assert response.ok?
19
21
  assert_equal 'Hello World', response.body
20
22
  end
21
23
 
22
- it 'can be used as Rack middleware' do
23
- app = lambda { |env| [200, {}, ['Goodbye World']] }
24
- mock_middleware =
25
- mock_app {
26
- get '/' do
27
- 'Hello World'
28
- end
29
- get '/goodbye' do
30
- @app.call(request.env)
31
- end
32
- }
33
- middleware = mock_middleware.new(app)
24
+ class TestApp < Sinatra::Base
25
+ get '/state' do
26
+ body = "Foo: #{@foo}"
27
+ @foo = 'discard'
28
+ body
29
+ end
30
+ end
31
+
32
+ it 'does not maintain state between requests' do
33
+ request = Rack::MockRequest.new(TestApp)
34
+ 2.times do
35
+ response = request.get('/state')
36
+ assert response.ok?
37
+ assert_equal 'Foo: ', response.body
38
+ end
39
+ end
40
+ end
41
+
42
+ describe "Sinatra::Base as Rack middleware" do
43
+
44
+ app = lambda { |env|
45
+ [210, {'X-Downstream' => 'true'}, ['Hello from downstream']] }
46
+
47
+ class TestMiddleware < Sinatra::Base
48
+ end
49
+
50
+ it 'creates a middleware that responds to #call with .new' do
51
+ middleware = TestMiddleware.new(app)
52
+ assert middleware.respond_to?(:call)
53
+ end
54
+
55
+ it 'exposes the downstream app' do
56
+ middleware = TestMiddleware.new(app)
34
57
  assert_same app, middleware.app
58
+ end
35
59
 
36
- request = Rack::MockRequest.new(middleware)
60
+ class TestMiddleware < Sinatra::Base
61
+ get '/' do
62
+ 'Hello from middleware'
63
+ end
64
+ end
65
+
66
+ middleware = TestMiddleware.new(app)
67
+ request = Rack::MockRequest.new(middleware)
68
+
69
+ it 'intercepts requests' do
37
70
  response = request.get('/')
38
71
  assert response.ok?
39
- assert_equal 'Hello World', response.body
72
+ assert_equal 'Hello from middleware', response.body
73
+ end
40
74
 
41
- response = request.get('/goodbye')
42
- assert response.ok?
43
- assert_equal 'Goodbye World', response.body
75
+ it 'automatically forwards requests downstream when no matching route found' do
76
+ response = request.get('/missing')
77
+ assert_equal 210, response.status
78
+ assert_equal 'Hello from downstream', response.body
44
79
  end
45
80
 
46
- it 'can take multiple definitions of a route' do
47
- app = mock_app {
48
- user_agent(/Foo/)
49
- get '/foo' do
50
- 'foo'
51
- end
81
+ class TestMiddleware < Sinatra::Base
82
+ get '/low-level-forward' do
83
+ app.call(env)
84
+ end
85
+ end
52
86
 
53
- get '/foo' do
54
- 'not foo'
55
- end
56
- }
87
+ it 'can call the downstream app directly and return result' do
88
+ response = request.get('/low-level-forward')
89
+ assert_equal 210, response.status
90
+ assert_equal 'true', response['X-Downstream']
91
+ assert_equal 'Hello from downstream', response.body
92
+ end
57
93
 
58
- request = Rack::MockRequest.new(app)
59
- response = request.get('/foo', 'HTTP_USER_AGENT' => 'Foo')
60
- assert response.ok?
61
- assert_equal 'foo', response.body
94
+ class TestMiddleware < Sinatra::Base
95
+ get '/explicit-forward' do
96
+ response['X-Middleware'] = 'true'
97
+ res = forward
98
+ assert_nil res
99
+ assert_equal 210, response.status
100
+ assert_equal 'true', response['X-Downstream']
101
+ assert_equal ['Hello from downstream'], response.body
102
+ 'Hello after explicit forward'
103
+ end
104
+ end
62
105
 
63
- request = Rack::MockRequest.new(app)
64
- response = request.get('/foo')
65
- assert response.ok?
66
- assert_equal 'not foo', response.body
106
+ it 'forwards the request downstream and integrates the response into the current context' do
107
+ response = request.get('/explicit-forward')
108
+ assert_equal 210, response.status
109
+ assert_equal 'true', response['X-Downstream']
110
+ assert_equal 'Hello after explicit forward', response.body
111
+ assert_equal '28', response['Content-Length']
112
+ end
113
+
114
+ app_content_length = lambda {|env|
115
+ [200, {'Content-Length' => '16'}, 'From downstream!']}
116
+ class TestMiddlewareContentLength < Sinatra::Base
117
+ get '/forward' do
118
+ res = forward
119
+ 'From after explicit forward!'
120
+ end
121
+ end
122
+
123
+ middleware_content_length = TestMiddlewareContentLength.new(app_content_length)
124
+ request_content_length = Rack::MockRequest.new(middleware_content_length)
125
+
126
+ it "sets content length for last response" do
127
+ response = request_content_length.get('/forward')
128
+ assert_equal '28', response['Content-Length']
67
129
  end
68
130
  end
data/test/erb_test.rb CHANGED
@@ -47,4 +47,35 @@ describe "ERB Templates" do
47
47
  assert ok?
48
48
  assert_equal "ERB Layout!\nHello World\n", body
49
49
  end
50
+
51
+ it "renders erb with blocks" do
52
+ mock_app {
53
+ def container
54
+ @_out_buf << "THIS."
55
+ yield
56
+ @_out_buf << "SPARTA!"
57
+ end
58
+ def is; "IS." end
59
+ get '/' do
60
+ erb '<% container do %> <%= is %> <% end %>'
61
+ end
62
+ }
63
+ get '/'
64
+ assert ok?
65
+ assert_equal 'THIS. IS. SPARTA!', body
66
+ end
67
+
68
+ it "can be used in a nested fashion for partials and whatnot" do
69
+ mock_app {
70
+ template(:inner) { "<inner><%= 'hi' %></inner>" }
71
+ template(:outer) { "<outer><%= erb :inner %></outer>" }
72
+ get '/' do
73
+ erb :outer
74
+ end
75
+ }
76
+
77
+ get '/'
78
+ assert ok?
79
+ assert_equal '<outer><inner>hi</inner></outer>', body
80
+ end
50
81
  end