sinatra-sinatra 0.10.0 → 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- 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"
|