sinatra-sinatra 0.10.0 → 0.10.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.
- data/CHANGES +9 -0
- data/README.rdoc +50 -0
- data/lib/sinatra/base.rb +98 -94
- data/sinatra.gemspec +4 -4
- data/test/filter_test.rb +12 -0
- data/test/mapped_error_test.rb +31 -0
- data/test/options_test.rb +7 -2
- data/test/routing_test.rb +35 -0
- data/test/static_test.rb +7 -0
- data/test/templates_test.rb +21 -2
- metadata +5 -3
data/CHANGES
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
= 1.0 / unreleased
|
2
|
+
|
3
|
+
* Route handlers, before filters, templates, error mappings, and
|
4
|
+
middleware are now resolved dynamically up the inheritance hierarchy
|
5
|
+
when needed instead of duplicating the superclass's version when
|
6
|
+
a new Sinatra::Base subclass is created. This should fix a variety
|
7
|
+
of issues with extensions that need to add any of these things
|
8
|
+
to the base class.
|
9
|
+
|
1
10
|
= 0.9.2 / 2009-05-18
|
2
11
|
|
3
12
|
* This version is compatible with Rack 1.0. [Rein Henrichs]
|
data/README.rdoc
CHANGED
@@ -470,6 +470,56 @@ recommended:
|
|
470
470
|
NOTE: The built-in Sinatra::Test module and Sinatra::TestHarness class
|
471
471
|
are deprecated as of the 0.9.2 release.
|
472
472
|
|
473
|
+
== Sinatra::Base - Middleware, Libraries, and Modular Apps
|
474
|
+
|
475
|
+
Defining your app at the top-level works well for micro-apps but has
|
476
|
+
considerable drawbacks when building reuseable components such as Rack
|
477
|
+
middleware, Rails metal, simple libraries with a server component, or
|
478
|
+
even Sinatra extensions. The top-level DSL pollutes the Object namespace
|
479
|
+
and assumes a micro-app style configuration (e.g., a single application
|
480
|
+
file, ./public and ./views directories, logging, exception detail page,
|
481
|
+
etc.). That's where Sinatra::Base comes into play:
|
482
|
+
|
483
|
+
require 'sinatra/base'
|
484
|
+
|
485
|
+
class MyApp < Sinatra::Base
|
486
|
+
set :sessions, true
|
487
|
+
set :foo, 'bar'
|
488
|
+
|
489
|
+
get '/' do
|
490
|
+
'Hello world!'
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
The MyApp class is an independent Rack component that can act as
|
495
|
+
Rack middleware, a Rack application, or Rails metal. You can +use+ or
|
496
|
+
+run+ this class from a rackup +config.ru+ file; or, control a server
|
497
|
+
component shipped as a library:
|
498
|
+
|
499
|
+
MyApp.run! :host => 'localhost', :port => 9090
|
500
|
+
|
501
|
+
The methods available to Sinatra::Base subclasses are exactly as those
|
502
|
+
available via the top-level DSL. Most top-level apps can be converted to
|
503
|
+
Sinatra::Base components with two modifications:
|
504
|
+
|
505
|
+
* Your file should require +sinatra/base+ instead of +sinatra+;
|
506
|
+
otherwise, all of Sinatra's DSL methods are imported into the main
|
507
|
+
namespace.
|
508
|
+
* Put your app's routes, error handlers, filters, and options in a subclass
|
509
|
+
of Sinatra::Base.
|
510
|
+
|
511
|
+
+Sinatra::Base+ is a blank slate. Most options are disabled by default,
|
512
|
+
including the built-in server. See {Options and Configuration}[http://sinatra.github.com/configuration.html]
|
513
|
+
for details on available options and their behavior.
|
514
|
+
|
515
|
+
SIDEBAR: Sinatra's top-level DSL is implemented using a simple delegation
|
516
|
+
system. The +Sinatra::Application+ class -- a special subclass of
|
517
|
+
Sinatra::Base -- receives all :get, :put, :post, :delete, :before,
|
518
|
+
:error, :not_found, :configure, and :set messages sent to the
|
519
|
+
top-level. Have a look at the code for yourself: here's the
|
520
|
+
{Sinatra::Delegator mixin}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1064]
|
521
|
+
being {included into the main namespace}[http://github.com/sinatra/sinatra/blob/master/lib/sinatra/main.rb#L25].
|
522
|
+
|
473
523
|
== Command line
|
474
524
|
|
475
525
|
Sinatra applications can be run directly:
|
data/lib/sinatra/base.rb
CHANGED
@@ -6,7 +6,7 @@ require 'rack/builder'
|
|
6
6
|
require 'sinatra/showexceptions'
|
7
7
|
|
8
8
|
module Sinatra
|
9
|
-
VERSION = '0.10.
|
9
|
+
VERSION = '0.10.1'
|
10
10
|
|
11
11
|
# The request object. See Rack::Request for more info:
|
12
12
|
# http://rack.rubyforge.org/doc/classes/Rack/Request.html
|
@@ -270,23 +270,33 @@ module Sinatra
|
|
270
270
|
def lookup_template(engine, template, views_dir, filename = nil, line = nil)
|
271
271
|
case template
|
272
272
|
when Symbol
|
273
|
-
|
274
|
-
lookup_template(engine, cached[:template], views_dir, cached[:filename], cached[:line])
|
275
|
-
else
|
276
|
-
path = ::File.join(views_dir, "#{template}.#{engine}")
|
277
|
-
[ ::File.read(path), path, 1 ]
|
278
|
-
end
|
273
|
+
load_template(engine, template, views_dir, options)
|
279
274
|
when Proc
|
280
275
|
filename, line = self.class.caller_locations.first if filename.nil?
|
281
|
-
[
|
276
|
+
[template.call, filename, line.to_i]
|
282
277
|
when String
|
283
278
|
filename, line = self.class.caller_locations.first if filename.nil?
|
284
|
-
[
|
279
|
+
[template, filename, line.to_i]
|
285
280
|
else
|
286
281
|
raise ArgumentError
|
287
282
|
end
|
288
283
|
end
|
289
284
|
|
285
|
+
def load_template(engine, template, views_dir, options={})
|
286
|
+
base = self.class
|
287
|
+
while base.respond_to?(:templates)
|
288
|
+
if cached = base.templates[template]
|
289
|
+
return lookup_template(engine, cached[:template], views_dir, cached[:filename], cached[:line])
|
290
|
+
else
|
291
|
+
base = base.superclass
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
# If no template exists in the cache, try loading from disk.
|
296
|
+
path = ::File.join(views_dir, "#{template}.#{engine}")
|
297
|
+
[ ::File.read(path), path, 1 ]
|
298
|
+
end
|
299
|
+
|
290
300
|
def lookup_layout(engine, template, views_dir)
|
291
301
|
lookup_template(engine, template, views_dir)
|
292
302
|
rescue Errno::ENOENT
|
@@ -357,7 +367,7 @@ module Sinatra
|
|
357
367
|
@env = env
|
358
368
|
@request = Request.new(env)
|
359
369
|
@response = Response.new
|
360
|
-
@params =
|
370
|
+
@params = indifferent_params(@request.params)
|
361
371
|
|
362
372
|
invoke { dispatch! }
|
363
373
|
invoke { error_block!(response.status) }
|
@@ -405,21 +415,15 @@ module Sinatra
|
|
405
415
|
end
|
406
416
|
|
407
417
|
private
|
408
|
-
# Run before filters
|
409
|
-
def
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
indifferent_params(@request.params)
|
414
|
-
else
|
415
|
-
nested_params(@request.params)
|
416
|
-
end
|
417
|
-
|
418
|
-
# before filters
|
419
|
-
self.class.filters.each { |block| instance_eval(&block) }
|
418
|
+
# Run before filters defined on the class and all superclasses.
|
419
|
+
def filter!(base=self.class)
|
420
|
+
filter!(base.superclass) if base.superclass.respond_to?(:filters)
|
421
|
+
base.filters.each { |block| instance_eval(&block) }
|
422
|
+
end
|
420
423
|
|
421
|
-
|
422
|
-
|
424
|
+
# Run routes defined on the class and all superclasses.
|
425
|
+
def route!(base=self.class)
|
426
|
+
if routes = base.routes[@request.request_method]
|
423
427
|
original_params = @params
|
424
428
|
path = unescape(@request.path_info)
|
425
429
|
|
@@ -451,6 +455,14 @@ module Sinatra
|
|
451
455
|
end
|
452
456
|
end
|
453
457
|
end
|
458
|
+
|
459
|
+
@params = original_params
|
460
|
+
end
|
461
|
+
|
462
|
+
# Run routes defined in superclass.
|
463
|
+
if base.superclass.respond_to?(:routes)
|
464
|
+
route! base.superclass
|
465
|
+
return
|
454
466
|
end
|
455
467
|
|
456
468
|
route_missing
|
@@ -474,6 +486,19 @@ module Sinatra
|
|
474
486
|
end
|
475
487
|
end
|
476
488
|
|
489
|
+
# Attempt to serve static files from public directory. Throws :halt when
|
490
|
+
# a matching file is found, returns nil otherwise.
|
491
|
+
def static!
|
492
|
+
return if (public_dir = options.public).nil?
|
493
|
+
public_dir = File.expand_path(public_dir)
|
494
|
+
|
495
|
+
path = File.expand_path(public_dir + unescape(request.path_info))
|
496
|
+
return if path[0, public_dir.length] != public_dir
|
497
|
+
return unless File.file?(path)
|
498
|
+
|
499
|
+
send_file path, :disposition => nil
|
500
|
+
end
|
501
|
+
|
477
502
|
# Enable string or symbol key access to the nested params hash.
|
478
503
|
def indifferent_params(params)
|
479
504
|
params = indifferent_hash.merge(params)
|
@@ -483,23 +508,6 @@ module Sinatra
|
|
483
508
|
end
|
484
509
|
end
|
485
510
|
|
486
|
-
# Recursively replace the params hash with a nested indifferent
|
487
|
-
# hash. Rack 1.0 has a built in implementation of this method - remove
|
488
|
-
# this once Rack 1.0 is required.
|
489
|
-
def nested_params(params)
|
490
|
-
return indifferent_hash.merge(params) if !params.keys.join.include?('[')
|
491
|
-
params.inject indifferent_hash do |res, (key,val)|
|
492
|
-
if key.include?('[')
|
493
|
-
head = key.split(/[\]\[]+/)
|
494
|
-
last = head.pop
|
495
|
-
head.inject(res){ |hash,k| hash[k] ||= indifferent_hash }[last] = val
|
496
|
-
else
|
497
|
-
res[key] = val
|
498
|
-
end
|
499
|
-
res
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
511
|
def indifferent_hash
|
504
512
|
Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
505
513
|
end
|
@@ -539,6 +547,8 @@ module Sinatra
|
|
539
547
|
|
540
548
|
# Dispatch a request with error handling.
|
541
549
|
def dispatch!
|
550
|
+
filter!
|
551
|
+
static! if options.static? && (request.get? || request.head?)
|
542
552
|
route!
|
543
553
|
rescue NotFound => boom
|
544
554
|
handle_not_found!(boom)
|
@@ -565,11 +575,16 @@ module Sinatra
|
|
565
575
|
|
566
576
|
# Find an custom error block for the key(s) specified.
|
567
577
|
def error_block!(*keys)
|
568
|
-
errmap = self.class.errors
|
569
578
|
keys.each do |key|
|
570
|
-
|
571
|
-
|
572
|
-
|
579
|
+
base = self.class
|
580
|
+
while base.respond_to?(:errors)
|
581
|
+
if block = base.errors[key]
|
582
|
+
# found a handler, eval and return result
|
583
|
+
res = instance_eval(&block)
|
584
|
+
return res
|
585
|
+
else
|
586
|
+
base = base.superclass
|
587
|
+
end
|
573
588
|
end
|
574
589
|
end
|
575
590
|
nil
|
@@ -591,18 +606,37 @@ module Sinatra
|
|
591
606
|
}.map! { |line| line.gsub(/^\.\//, '') }
|
592
607
|
end
|
593
608
|
|
594
|
-
@routes = {}
|
595
|
-
@filters = []
|
596
|
-
@conditions = []
|
597
|
-
@templates = {}
|
598
|
-
@middleware = []
|
599
|
-
@errors = {}
|
600
|
-
@prototype = nil
|
601
|
-
@extensions = []
|
602
|
-
|
603
609
|
class << self
|
604
|
-
|
605
|
-
|
610
|
+
attr_reader :routes, :filters, :templates, :errors
|
611
|
+
|
612
|
+
def reset!
|
613
|
+
@conditions = []
|
614
|
+
@routes = {}
|
615
|
+
@filters = []
|
616
|
+
@templates = {}
|
617
|
+
@errors = {}
|
618
|
+
@middleware = []
|
619
|
+
@prototype = nil
|
620
|
+
@extensions = []
|
621
|
+
end
|
622
|
+
|
623
|
+
# Extension modules registered on this class and all superclasses.
|
624
|
+
def extensions
|
625
|
+
if superclass.respond_to?(:extensions)
|
626
|
+
(@extensions + superclass.extensions).uniq
|
627
|
+
else
|
628
|
+
@extensions
|
629
|
+
end
|
630
|
+
end
|
631
|
+
|
632
|
+
# Middleware used in this class and all superclasses.
|
633
|
+
def middleware
|
634
|
+
if superclass.respond_to?(:middleware)
|
635
|
+
superclass.middleware + @middleware
|
636
|
+
else
|
637
|
+
@middleware
|
638
|
+
end
|
639
|
+
end
|
606
640
|
|
607
641
|
# Sets an option to the given value. If the value is a proc,
|
608
642
|
# the proc will be called every time the option is accessed.
|
@@ -770,7 +804,7 @@ module Sinatra
|
|
770
804
|
|
771
805
|
invoke_hook(:route_added, verb, path, block)
|
772
806
|
|
773
|
-
(routes[verb] ||= []).
|
807
|
+
(@routes[verb] ||= []).
|
774
808
|
push([pattern, keys, conditions, block]).last
|
775
809
|
end
|
776
810
|
|
@@ -813,10 +847,6 @@ module Sinatra
|
|
813
847
|
include(*extensions) if extensions.any?
|
814
848
|
end
|
815
849
|
|
816
|
-
def extensions
|
817
|
-
(@extensions + (superclass.extensions rescue [])).uniq
|
818
|
-
end
|
819
|
-
|
820
850
|
def register(*extensions, &block)
|
821
851
|
extensions << Module.new(&block) if block_given?
|
822
852
|
@extensions += extensions
|
@@ -875,8 +905,8 @@ module Sinatra
|
|
875
905
|
builder.use Rack::CommonLogger if logging?
|
876
906
|
builder.use Rack::MethodOverride if methodoverride?
|
877
907
|
builder.use ShowExceptions if show_exceptions?
|
908
|
+
middleware.each { |c,a,b| builder.use(c, *a, &b) }
|
878
909
|
|
879
|
-
@middleware.each { |c,a,b| builder.use(c, *a, &b) }
|
880
910
|
builder.run super
|
881
911
|
builder.to_app
|
882
912
|
end
|
@@ -885,25 +915,6 @@ module Sinatra
|
|
885
915
|
synchronize { prototype.call(env) }
|
886
916
|
end
|
887
917
|
|
888
|
-
def reset!(base=superclass)
|
889
|
-
@routes = base.dupe_routes
|
890
|
-
@templates = base.templates.dup
|
891
|
-
@conditions = []
|
892
|
-
@filters = base.filters.dup
|
893
|
-
@errors = base.errors.dup
|
894
|
-
@middleware = base.middleware.dup
|
895
|
-
@prototype = nil
|
896
|
-
@extensions = []
|
897
|
-
end
|
898
|
-
|
899
|
-
protected
|
900
|
-
def dupe_routes
|
901
|
-
routes.inject({}) do |hash,(request_method,routes)|
|
902
|
-
hash[request_method] = routes.dup
|
903
|
-
hash
|
904
|
-
end
|
905
|
-
end
|
906
|
-
|
907
918
|
private
|
908
919
|
def detect_rack_handler
|
909
920
|
servers = Array(self.server)
|
@@ -918,7 +929,7 @@ module Sinatra
|
|
918
929
|
end
|
919
930
|
|
920
931
|
def inherited(subclass)
|
921
|
-
subclass.reset!
|
932
|
+
subclass.reset!
|
922
933
|
super
|
923
934
|
end
|
924
935
|
|
@@ -942,7 +953,7 @@ module Sinatra
|
|
942
953
|
/\(.*\)/, # generated code
|
943
954
|
/custom_require\.rb$/, # rubygems require hacks
|
944
955
|
/active_support/, # active_support require hacks
|
945
|
-
]
|
956
|
+
]
|
946
957
|
|
947
958
|
# add rubinius (and hopefully other VM impls) ignore patterns ...
|
948
959
|
CALLERS_TO_IGNORE.concat(RUBY_IGNORE_CALLERS) if defined?(RUBY_IGNORE_CALLERS)
|
@@ -961,10 +972,12 @@ module Sinatra
|
|
961
972
|
end
|
962
973
|
end
|
963
974
|
|
975
|
+
reset!
|
976
|
+
|
964
977
|
set :raise_errors, true
|
965
978
|
set :dump_errors, false
|
966
979
|
set :clean_trace, true
|
967
|
-
set :show_exceptions,
|
980
|
+
set :show_exceptions, false
|
968
981
|
set :sessions, false
|
969
982
|
set :logging, false
|
970
983
|
set :methodoverride, false
|
@@ -982,16 +995,6 @@ module Sinatra
|
|
982
995
|
set :public, Proc.new { root && File.join(root, 'public') }
|
983
996
|
set :lock, false
|
984
997
|
|
985
|
-
# static files route
|
986
|
-
get(/.*[^\/]$/) do
|
987
|
-
pass unless options.static? && options.public?
|
988
|
-
public_dir = File.expand_path(options.public)
|
989
|
-
path = File.expand_path(public_dir + unescape(request.path_info))
|
990
|
-
pass if path[0, public_dir.length] != public_dir
|
991
|
-
pass unless File.file?(path)
|
992
|
-
send_file path, :disposition => nil
|
993
|
-
end
|
994
|
-
|
995
998
|
error ::Exception do
|
996
999
|
response.status = 500
|
997
1000
|
content_type 'text/html'
|
@@ -1035,6 +1038,7 @@ module Sinatra
|
|
1035
1038
|
# Base class for classic style (top-level) applications.
|
1036
1039
|
class Default < Base
|
1037
1040
|
set :raise_errors, Proc.new { test? }
|
1041
|
+
set :show_exceptions, Proc.new { development? }
|
1038
1042
|
set :dump_errors, true
|
1039
1043
|
set :sessions, false
|
1040
1044
|
set :logging, Proc.new { ! test? }
|
data/sinatra.gemspec
CHANGED
@@ -3,13 +3,13 @@ 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.10.
|
7
|
-
s.date = '2009-06-
|
6
|
+
s.version = '0.10.1'
|
7
|
+
s.date = '2009-06-07'
|
8
8
|
|
9
9
|
s.description = "Classy web-development dressed in a DSL"
|
10
10
|
s.summary = "Classy web-development dressed in a DSL"
|
11
11
|
|
12
|
-
s.authors = ["Blake Mizerany"]
|
12
|
+
s.authors = ["Blake Mizerany", "Ryan Tomayko", "Simon Rozet"]
|
13
13
|
s.email = "sinatrarb@googlegroups.com"
|
14
14
|
|
15
15
|
# = MANIFEST =
|
@@ -71,7 +71,7 @@ Gem::Specification.new do |s|
|
|
71
71
|
|
72
72
|
s.extra_rdoc_files = %w[README.rdoc LICENSE]
|
73
73
|
s.add_dependency 'rack', '>= 1.0'
|
74
|
-
s.add_development_dependency 'shotgun', '>= 0.
|
74
|
+
s.add_development_dependency 'shotgun', '>= 0.3', '< 1.0'
|
75
75
|
s.add_development_dependency 'rack-test', '>= 0.3.0'
|
76
76
|
|
77
77
|
s.has_rdoc = true
|
data/test/filter_test.rb
CHANGED
@@ -96,4 +96,16 @@ class FilterTest < Test::Unit::TestCase
|
|
96
96
|
assert ok?
|
97
97
|
assert_equal 'cool', body
|
98
98
|
end
|
99
|
+
|
100
|
+
it "runs filters defined in superclasses" do
|
101
|
+
base = Class.new(Sinatra::Base)
|
102
|
+
base.before { @foo = 'hello from superclass' }
|
103
|
+
|
104
|
+
mock_app(base) {
|
105
|
+
get('/foo') { @foo }
|
106
|
+
}
|
107
|
+
|
108
|
+
get '/foo'
|
109
|
+
assert_equal 'hello from superclass', body
|
110
|
+
end
|
99
111
|
end
|
data/test/mapped_error_test.rb
CHANGED
@@ -101,6 +101,37 @@ class MappedErrorTest < Test::Unit::TestCase
|
|
101
101
|
assert_equal 404, status
|
102
102
|
assert_equal "Lost, are we?", body
|
103
103
|
end
|
104
|
+
|
105
|
+
it 'inherits error mappings from base class' do
|
106
|
+
base = Class.new(Sinatra::Base)
|
107
|
+
base.error(FooError) { 'base class' }
|
108
|
+
|
109
|
+
mock_app(base) {
|
110
|
+
set :raise_errors, false
|
111
|
+
get '/' do
|
112
|
+
raise FooError
|
113
|
+
end
|
114
|
+
}
|
115
|
+
|
116
|
+
get '/'
|
117
|
+
assert_equal 'base class', body
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'overrides error mappings in base class' do
|
121
|
+
base = Class.new(Sinatra::Base)
|
122
|
+
base.error(FooError) { 'base class' }
|
123
|
+
|
124
|
+
mock_app(base) {
|
125
|
+
set :raise_errors, false
|
126
|
+
error(FooError) { 'subclass' }
|
127
|
+
get '/' do
|
128
|
+
raise FooError
|
129
|
+
end
|
130
|
+
}
|
131
|
+
|
132
|
+
get '/'
|
133
|
+
assert_equal 'subclass', body
|
134
|
+
end
|
104
135
|
end
|
105
136
|
|
106
137
|
describe 'Custom Error Pages' do
|
data/test/options_test.rb
CHANGED
@@ -183,10 +183,15 @@ class OptionsTest < Test::Unit::TestCase
|
|
183
183
|
end
|
184
184
|
|
185
185
|
describe 'show_exceptions' do
|
186
|
+
%w[development test production none].each do |environment|
|
187
|
+
it "is disabled on Base in #{environment} environments" do
|
188
|
+
@base.set(:environment, environment)
|
189
|
+
assert ! @base.show_exceptions?
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
186
193
|
it 'is enabled on Default only in development' do
|
187
194
|
@base.set(:environment, :development)
|
188
|
-
assert @base.show_exceptions?
|
189
|
-
|
190
195
|
assert @default.development?
|
191
196
|
assert @default.show_exceptions?
|
192
197
|
|
data/test/routing_test.rb
CHANGED
@@ -781,4 +781,39 @@ class RoutingTest < Test::Unit::TestCase
|
|
781
781
|
end
|
782
782
|
|
783
783
|
end
|
784
|
+
|
785
|
+
it "matches routes defined in superclasses" do
|
786
|
+
base = Class.new(Sinatra::Base)
|
787
|
+
base.get('/foo') { 'foo in baseclass' }
|
788
|
+
|
789
|
+
mock_app(base) {
|
790
|
+
get('/bar') { 'bar in subclass' }
|
791
|
+
}
|
792
|
+
|
793
|
+
get '/foo'
|
794
|
+
assert ok?
|
795
|
+
assert_equal 'foo in baseclass', body
|
796
|
+
|
797
|
+
get '/bar'
|
798
|
+
assert ok?
|
799
|
+
assert_equal 'bar in subclass', body
|
800
|
+
end
|
801
|
+
|
802
|
+
it "matches routes in subclasses before superclasses" do
|
803
|
+
base = Class.new(Sinatra::Base)
|
804
|
+
base.get('/foo') { 'foo in baseclass' }
|
805
|
+
base.get('/bar') { 'bar in baseclass' }
|
806
|
+
|
807
|
+
mock_app(base) {
|
808
|
+
get('/foo') { 'foo in subclass' }
|
809
|
+
}
|
810
|
+
|
811
|
+
get '/foo'
|
812
|
+
assert ok?
|
813
|
+
assert_equal 'foo in subclass', body
|
814
|
+
|
815
|
+
get '/bar'
|
816
|
+
assert ok?
|
817
|
+
assert_equal 'bar in baseclass', body
|
818
|
+
end
|
784
819
|
end
|
data/test/static_test.rb
CHANGED
@@ -34,6 +34,13 @@ class StaticTest < Test::Unit::TestCase
|
|
34
34
|
assert response.headers.include?('Last-Modified')
|
35
35
|
end
|
36
36
|
|
37
|
+
%w[POST PUT DELETE].each do |verb|
|
38
|
+
it "does not serve #{verb} requests" do
|
39
|
+
send verb.downcase, "/#{File.basename(__FILE__)}"
|
40
|
+
assert_equal 404, status
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
37
44
|
it 'serves files in preference to custom routes' do
|
38
45
|
@app.get("/#{File.basename(__FILE__)}") { 'Hello World' }
|
39
46
|
get "/#{File.basename(__FILE__)}"
|
data/test/templates_test.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/helper'
|
2
2
|
|
3
3
|
class TemplatesTest < Test::Unit::TestCase
|
4
|
-
def render_app(&block)
|
5
|
-
mock_app {
|
4
|
+
def render_app(base=Sinatra::Base, &block)
|
5
|
+
mock_app(base) {
|
6
6
|
def render_test(template, data, options, locals, &block)
|
7
7
|
inner = block ? block.call : ''
|
8
8
|
data + inner
|
@@ -107,6 +107,25 @@ class TemplatesTest < Test::Unit::TestCase
|
|
107
107
|
assert ok?
|
108
108
|
assert_equal 'Hello Mike!<p>content</p>', body
|
109
109
|
end
|
110
|
+
|
111
|
+
it 'loads templates defined in subclasses' do
|
112
|
+
base = Class.new(Sinatra::Base)
|
113
|
+
base.template(:foo) { 'bar' }
|
114
|
+
render_app(base) { render :test, :foo }
|
115
|
+
assert ok?
|
116
|
+
assert_equal 'bar', body
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'uses templates in superclasses before subclasses' do
|
120
|
+
base = Class.new(Sinatra::Base)
|
121
|
+
base.template(:foo) { 'template in superclass' }
|
122
|
+
render_app(base) { render :test, :foo }
|
123
|
+
@app.template(:foo) { 'template in subclass' }
|
124
|
+
|
125
|
+
get '/'
|
126
|
+
assert ok?
|
127
|
+
assert_equal 'template in subclass', body
|
128
|
+
end
|
110
129
|
end
|
111
130
|
|
112
131
|
# __END__ : this is not the real end of the script.
|
metadata
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sinatra-sinatra
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Mizerany
|
8
|
+
- Ryan Tomayko
|
9
|
+
- Simon Rozet
|
8
10
|
autorequire:
|
9
11
|
bindir: bin
|
10
12
|
cert_chain: []
|
11
13
|
|
12
|
-
date: 2009-06-
|
14
|
+
date: 2009-06-07 00:00:00 -07:00
|
13
15
|
default_executable:
|
14
16
|
dependencies:
|
15
17
|
- !ruby/object:Gem::Dependency
|
@@ -30,7 +32,7 @@ dependencies:
|
|
30
32
|
requirements:
|
31
33
|
- - ">="
|
32
34
|
- !ruby/object:Gem::Version
|
33
|
-
version: "0.
|
35
|
+
version: "0.3"
|
34
36
|
- - <
|
35
37
|
- !ruby/object:Gem::Version
|
36
38
|
version: "1.0"
|