Object
# File lib/sinatra/base.rb, line 978 978: def call(env) 979: synchronize { prototype.call(env) } 980: end
Like Kernel#caller but excluding certain magic entries and without line / method information; the resulting array contains filenames only.
# File lib/sinatra/base.rb, line 1028 1028: def caller_files 1029: caller_locations. 1030: map { |file,line| file } 1031: end
# File lib/sinatra/base.rb, line 1033 1033: def caller_locations 1034: caller(1). 1035: map { |line| line.split(/:(?=\d|in )/)[0,2] }. 1036: reject { |file,line| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } } 1037: end
Set configuration options for Sinatra and/or the app. Allows scoping of settings for certain environments.
# File lib/sinatra/base.rb, line 928 928: def configure(*envs, &block) 929: yield self if envs.empty? || envs.include?(environment.to_sym) 930: end
# File lib/sinatra/base.rb, line 846 846: def delete(path, opts={}, &bk); route 'DELETE', path, opts, &bk end
# File lib/sinatra/base.rb, line 922 922: def development?; environment == :development end
Defining a `GET` handler also automatically defines a `HEAD` handler.
# File lib/sinatra/base.rb, line 836 836: def get(path, opts={}, &block) 837: conditions = @conditions.dup 838: route('GET', path, opts, &block) 839: 840: @conditions = conditions 841: route('HEAD', path, opts, &block) 842: end
# File lib/sinatra/base.rb, line 847 847: def head(path, opts={}, &bk); route 'HEAD', path, opts, &bk end
Makes the methods defined in the block and in the Modules given in `extensions` available to the handlers and templates
# File lib/sinatra/base.rb, line 908 908: def helpers(*extensions, &block) 909: class_eval(&block) if block_given? 910: include(*extensions) if extensions.any? 911: end
# File lib/sinatra/base.rb, line 391 391: def initialize(app=nil) 392: @app = app 393: @template_cache = Tilt::Cache.new 394: yield self if block_given? 395: end
Create a new instance of the class fronted by its middleware pipeline. The object is guaranteed to respond to # but may not be an instance of the class new was called on.
# File lib/sinatra/base.rb, line 966 966: def new(*args, &bk) 967: builder = Rack::Builder.new 968: builder.use Rack::Session::Cookie if sessions? 969: builder.use Rack::CommonLogger if logging? 970: builder.use Rack::MethodOverride if method_override? 971: builder.use ShowExceptions if show_exceptions? 972: middleware.each { |c,a,b| builder.use(c, *a, &b) } 973: 974: builder.run super 975: builder.to_app 976: end
# File lib/sinatra/base.rb, line 845 845: def post(path, opts={}, &bk); route 'POST', path, opts, &bk end
# File lib/sinatra/base.rb, line 923 923: def production?; environment == :production end
The prototype instance used to process requests.
# File lib/sinatra/base.rb, line 959 959: def prototype 960: @prototype ||= new 961: end
# File lib/sinatra/base.rb, line 844 844: def put(path, opts={}, &bk); route 'PUT', path, opts, &bk end
# File lib/sinatra/base.rb, line 913 913: def register(*extensions, &block) 914: extensions << Module.new(&block) if block_given? 915: @extensions += extensions 916: extensions.each do |extension| 917: extend extension 918: extension.registered(self) if extension.respond_to?(:registered) 919: end 920: end
Run the Sinatra app as a self-hosted server using Thin, Mongrel or WEBrick (in that order)
# File lib/sinatra/base.rb, line 940 940: def run!(options={}) 941: set options 942: handler = detect_rack_handler 943: handler_name = handler.name.gsub(/.*::/, '') 944: puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " + 945: "on #{port} for #{environment} with backup from #{handler_name}" unless handler_name =~/cgi/ 946: handler.run self, :Host => bind, :Port => port do |server| 947: trap(:INT) do 948: ## Use thins' hard #stop! if available, otherwise just #stop 949: server.respond_to?(:stop!) ? server.stop! : server.stop 950: puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/ 951: end 952: set :running, true 953: end 954: rescue Errno::EADDRINUSE => e 955: puts "== Someone is already performing on port #{port}!" 956: end
Define an after filter; runs after all requests within the same context as route handlers and may access/modify the request and response.
# File lib/sinatra/base.rb, line 791 791: def after(&block) 792: @after_filters << block 793: end
Define a before filter; runs before all requests within the same context as route handlers and may access/modify the request and response.
# File lib/sinatra/base.rb, line 784 784: def before(&block) 785: @before_filters << block 786: end
# File lib/sinatra/base.rb, line 878 878: def compile(path) 879: keys = [] 880: if path.respond_to? :to_str 881: special_chars = %{. + ( )} 882: pattern = 883: path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match| 884: case match 885: when "*" 886: keys << 'splat' 887: "(.*?)" 888: when *special_chars 889: Regexp.escape(match) 890: else 891: keys << $2[1..1] 892: "([^/?&#]+)" 893: end 894: end 895: [/^#{pattern}$/, keys] 896: elsif path.respond_to?(:keys) && path.respond_to?(:match) 897: [path, path.keys] 898: elsif path.respond_to? :match 899: [path, keys] 900: else 901: raise TypeError, path 902: end 903: end
Add a route condition. The route is considered non-matching when the block returns false.
# File lib/sinatra/base.rb, line 797 797: def condition(&block) 798: @conditions << block 799: end
# File lib/sinatra/base.rb, line 983 983: def detect_rack_handler 984: servers = Array(self.server) 985: servers.each do |server_name| 986: begin 987: return Rack::Handler.get(server_name.downcase) 988: rescue LoadError 989: rescue NameError 990: end 991: end 992: fail "Server handler (#{servers.join(',')}) not found." 993: end
Same as calling `set :option, false` for each of the given options.
# File lib/sinatra/base.rb, line 719 719: def disable(*opts) 720: opts.each { |key| set(key, false) } 721: end
Same as calling `set :option, true` for each of the given options.
# File lib/sinatra/base.rb, line 714 714: def enable(*opts) 715: opts.each { |key| set(key, true) } 716: end
Define a custom error handler. Optionally takes either an Exception class, or an HTTP status code to specify which errors should be handled.
# File lib/sinatra/base.rb, line 726 726: def error(codes=Exception, &block) 727: Array(codes).each { |code| @errors[code] = block } 728: end
Extension modules registered on this class and all superclasses.
# File lib/sinatra/base.rb, line 677 677: def extensions 678: if superclass.respond_to?(:extensions) 679: (@extensions + superclass.extensions).uniq 680: else 681: @extensions 682: end 683: end
# File lib/sinatra/base.rb, line 802 802: def host_name(pattern) 803: condition { pattern === request.host } 804: end
# File lib/sinatra/base.rb, line 995 995: def inherited(subclass) 996: subclass.reset! 997: super 998: end
Load embeded templates from the file; uses the caller’s FILE when no file is specified.
# File lib/sinatra/base.rb, line 748 748: def inline_templates=(file=nil) 749: file = (file.nil? || file == true) ? caller_files.first : file 750: 751: begin 752: app, data = 753: ::IO.read(file).gsub("\r\n", "\n").split(/^__END__$/, 2) 754: rescue Errno::ENOENT 755: app, data = nil 756: end 757: 758: if data 759: lines = app.count("\n") + 1 760: template = nil 761: data.each_line do |line| 762: lines += 1 763: if line =~ /^@@\s*(.*)/ 764: template = '' 765: templates[$1.to_sym] = [template, file, lines] 766: elsif template 767: template << line 768: end 769: end 770: end 771: end
# File lib/sinatra/base.rb, line 874 874: def invoke_hook(name, *args) 875: extensions.each { |e| e.send(name, *args) if e.respond_to?(name) } 876: end
Define the layout template. The block must return the template source.
# File lib/sinatra/base.rb, line 742 742: def layout(name=:layout, &block) 743: template name, &block 744: end
# File lib/sinatra/base.rb, line 1009 1009: def metadef(message, &block) 1010: (class << self; self; end). 1011: send :define_method, message, &block 1012: end
Middleware used in this class and all superclasses.
# File lib/sinatra/base.rb, line 686 686: def middleware 687: if superclass.respond_to?(:middleware) 688: superclass.middleware + @middleware 689: else 690: @middleware 691: end 692: end
Lookup or register a mime type in Rack’s mime registry.
# File lib/sinatra/base.rb, line 774 774: def mime_type(type, value=nil) 775: return type if type.nil? || type.to_s.include?('/') 776: type = ".#{type}" unless type.to_s[0] == .. 777: return Rack::Mime.mime_type(type, nil) unless value 778: Rack::Mime::MIME_TYPES[type] = value 779: end
Sugar for `error(404) { … }`
# File lib/sinatra/base.rb, line 731 731: def not_found(&block) 732: error 404, &block 733: end
# File lib/sinatra/base.rb, line 818 818: def provides(*types) 819: types = [types] unless types.kind_of? Array 820: types.map!{|t| mime_type(t)} 821: 822: condition { 823: matching_types = (request.accept & types) 824: unless matching_types.empty? 825: response.headers['Content-Type'] = matching_types.first 826: true 827: else 828: false 829: end 830: } 831: end
# File lib/sinatra/base.rb, line 659 659: def reset! 660: @conditions = [] 661: @routes = {} 662: @before_filters = [] 663: @after_filters = [] 664: @errors = {} 665: @middleware = [] 666: @prototype = nil 667: @extensions = [] 668: 669: if superclass.respond_to?(:templates) 670: @templates = Hash.new { |hash,key| superclass.templates[key] } 671: else 672: @templates = {} 673: end 674: end
# File lib/sinatra/base.rb, line 850 850: def route(verb, path, options={}, &block) 851: # Because of self.options.host 852: host_name(options.delete(:bind)) if options.key?(:host) 853: 854: options.each {|option, args| send(option, *args)} 855: 856: pattern, keys = compile(path) 857: conditions, @conditions = @conditions, [] 858: 859: define_method "#{verb} #{path}", &block 860: unbound_method = instance_method("#{verb} #{path}") 861: block = 862: if block.arity != 0 863: proc { unbound_method.bind(self).call(*@block_params) } 864: else 865: proc { unbound_method.bind(self).call } 866: end 867: 868: invoke_hook(:route_added, verb, path, block) 869: 870: (@routes[verb] ||= []). 871: push([pattern, keys, conditions, block]).last 872: end
Sets an option to the given value. If the value is a proc, the proc will be called every time the option is accessed.
# File lib/sinatra/base.rb, line 696 696: def set(option, value=self, &block) 697: raise ArgumentError if block && value != self 698: value = block if block 699: if value.kind_of?(Proc) 700: metadef(option, &value) 701: metadef("#{option}?") { !!__send__(option) } 702: metadef("#{option}=") { |val| metadef(option, &Proc.new{val}) } 703: elsif value == self && option.respond_to?(:to_hash) 704: option.to_hash.each { |k,v| set(k, v) } 705: elsif respond_to?("#{option}=") 706: __send__ "#{option}=", value 707: else 708: set option, Proc.new{value} 709: end 710: self 711: end
# File lib/sinatra/base.rb, line 1001 1001: def synchronize(&block) 1002: if lock? 1003: @@mutex.synchronize(&block) 1004: else 1005: yield 1006: end 1007: end
Rack call interface.
# File lib/sinatra/base.rb, line 398 398: def call(env) 399: dup.call!(env) 400: end
# File lib/sinatra/base.rb, line 404 404: def call!(env) 405: @env = env 406: @request = Request.new(env) 407: @response = Response.new 408: @params = indifferent_params(@request.params) 409: @template_cache.clear if settings.reload_templates 410: 411: invoke { dispatch! } 412: invoke { error_block!(response.status) } 413: 414: status, header, body = @response.finish 415: 416: # Never produce a body on HEAD requests. Do retain the Content-Length 417: # unless it's "0", in which case we assume it was calculated erroneously 418: # for a manual HEAD response and remove it entirely. 419: if @env['REQUEST_METHOD'] == 'HEAD' 420: body = [] 421: header.delete('Content-Length') if header['Content-Length'] == '0' 422: end 423: 424: [status, header, body] 425: end
Forward the request to the downstream app — middleware only.
# File lib/sinatra/base.rb, line 448 448: def forward 449: fail "downstream app not set" unless @app.respond_to? :call 450: status, headers, body = @app.call(@request.env) 451: @response.status = status 452: @response.body = body 453: @response.headers.merge! headers 454: nil 455: end
Exit the current block, halts any further processing of the request, and returns the specified response.
# File lib/sinatra/base.rb, line 435 435: def halt(*response) 436: response = response.first if response.length == 1 437: throw :halt, response 438: end
Pass control to the next matching route. If there are no more matching routes, Sinatra will return a 404 response.
# File lib/sinatra/base.rb, line 443 443: def pass(&block) 444: throw :pass, block 445: end
Access settings defined with Base.set.
# File lib/sinatra/base.rb, line 428 428: def settings 429: self.class 430: end
Run after filters defined on the class and all superclasses.
# File lib/sinatra/base.rb, line 465 465: def after_filter!(base=self.class) 466: after_filter!(base.superclass) if base.superclass.respond_to?(:after_filters) 467: base.after_filters.each { |block| instance_eval(&block) } 468: end
Run before filters defined on the class and all superclasses.
# File lib/sinatra/base.rb, line 459 459: def before_filter!(base=self.class) 460: before_filter!(base.superclass) if base.superclass.respond_to?(:before_filters) 461: base.before_filters.each { |block| instance_eval(&block) } 462: end
Dispatch a request with error handling.
# File lib/sinatra/base.rb, line 598 598: def dispatch! 599: static! if settings.static? && (request.get? || request.head?) 600: before_filter! 601: route! 602: rescue NotFound => boom 603: handle_not_found!(boom) 604: rescue ::Exception => boom 605: handle_exception!(boom) 606: ensure 607: after_filter! unless env['sinatra.static_file'] 608: end
# File lib/sinatra/base.rb, line 650 650: def dump_errors!(boom) 651: msg = ["#{boom.class} - #{boom.message}:", 652: *boom.backtrace].join("\n ") 653: @env['rack.errors'].puts(msg) 654: end
Find an custom error block for the key(s) specified.
# File lib/sinatra/base.rb, line 635 635: def error_block!(*keys) 636: keys.each do |key| 637: base = self.class 638: while base.respond_to?(:errors) 639: if block = base.errors[key] 640: # found a handler, eval and return result 641: return instance_eval(&block) 642: else 643: base = base.superclass 644: end 645: end 646: end 647: nil 648: end
# File lib/sinatra/base.rb, line 618 618: def handle_exception!(boom) 619: @env['sinatra.error'] = boom 620: 621: dump_errors!(boom) if settings.dump_errors? 622: raise boom if settings.show_exceptions? 623: 624: @response.status = 500 625: if res = error_block!(boom.class) 626: res 627: elsif settings.raise_errors? 628: raise boom 629: else 630: error_block!(Exception) 631: end 632: end
# File lib/sinatra/base.rb, line 610 610: def handle_not_found!(boom) 611: @env['sinatra.error'] = boom 612: @response.status = 404 613: @response.headers['X-Cascade'] = 'pass' 614: @response.body = ['<h1>Not Found</h1>'] 615: error_block! boom.class, NotFound 616: end
# File lib/sinatra/base.rb, line 560 560: def indifferent_hash 561: Hash.new {|hash,key| hash[key.to_s] if Symbol === key } 562: end
Enable string or symbol key access to the nested params hash.
# File lib/sinatra/base.rb, line 552 552: def indifferent_params(params) 553: params = indifferent_hash.merge(params) 554: params.each do |key, value| 555: next unless value.is_a?(Hash) 556: params[key] = indifferent_params(value) 557: end 558: end
Run the block with ‘throw :halt’ support and apply result to the response.
# File lib/sinatra/base.rb, line 565 565: def invoke(&block) 566: res = catch(:halt) { instance_eval(&block) } 567: return if res.nil? 568: 569: case 570: when res.respond_to?(:to_str) 571: @response.body = [res] 572: when res.respond_to?(:to_ary) 573: res = res.to_ary 574: if Fixnum === res.first 575: if res.length == 3 576: @response.status, headers, body = res 577: @response.body = body if body 578: headers.each { |k, v| @response.headers[k] = v } if headers 579: elsif res.length == 2 580: @response.status = res.first 581: @response.body = res.last 582: else 583: raise TypeError, "#{res.inspect} not supported" 584: end 585: else 586: @response.body = res 587: end 588: when res.respond_to?(:each) 589: @response.body = res 590: when (100...599) === res 591: @response.status = res 592: end 593: 594: res 595: end
Run routes defined on the class and all superclasses.
# File lib/sinatra/base.rb, line 471 471: def route!(base=self.class, pass_block=nil) 472: if routes = base.routes[@request.request_method] 473: original_params = @params 474: path = unescape(@request.path_info) 475: 476: routes.each do |pattern, keys, conditions, block| 477: if match = pattern.match(path) 478: values = match.captures.to_a 479: params = 480: if keys.any? 481: keys.zip(values).inject({}) do |hash,(k,v)| 482: if k == 'splat' 483: (hash[k] ||= []) << v 484: else 485: hash[k] = v 486: end 487: hash 488: end 489: elsif values.any? 490: {'captures' => values} 491: else 492: {} 493: end 494: @params = original_params.merge(params) 495: @block_params = values 496: 497: pass_block = catch(:pass) do 498: conditions.each { |cond| 499: throw :pass if instance_eval(&cond) == false } 500: route_eval(&block) 501: end 502: end 503: end 504: 505: @params = original_params 506: end 507: 508: # Run routes defined in superclass. 509: if base.superclass.respond_to?(:routes) 510: route! base.superclass, pass_block 511: return 512: end 513: 514: route_eval(&pass_block) if pass_block 515: 516: route_missing 517: end
Run a route block and throw :halt with the result.
# File lib/sinatra/base.rb, line 520 520: def route_eval(&block) 521: throw :halt, instance_eval(&block) 522: end
No matching route was found or all routes passed. The default implementation is to forward the request downstream when running as middleware (@app is non-nil); when no downstream app is set, raise a NotFound exception. Subclasses can override this method to perform custom route miss logic.
# File lib/sinatra/base.rb, line 529 529: def route_missing 530: if @app 531: forward 532: else 533: raise NotFound 534: end 535: end
Attempt to serve static files from public directory. Throws :halt when a matching file is found, returns nil otherwise.
# File lib/sinatra/base.rb, line 539 539: def static! 540: return if (public_dir = settings.public).nil? 541: public_dir = File.expand_path(public_dir) 542: 543: path = File.expand_path(public_dir + unescape(request.path_info)) 544: return if path[0, public_dir.length] != public_dir 545: return unless File.file?(path) 546: 547: env['sinatra.static_file'] = path 548: send_file path, :disposition => nil 549: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.