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.