Parent

Included Modules

Sinatra::Base

Base class for all Sinatra applications and middleware.

Constants

CALLERS_TO_IGNORE

Attributes

app[RW]
env[RW]
request[RW]
response[RW]
params[RW]
routes[R]
before_filters[R]
after_filters[R]
templates[R]
errors[R]

Public Class Methods

call(env) click to toggle source
     # File lib/sinatra/base.rb, line 978
978:       def call(env)
979:         synchronize { prototype.call(env) }
980:       end
caller_files() click to toggle source

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
caller_locations() click to toggle source
      # 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
configure(*envs, &block) click to toggle source

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
delete(path, opts={}, &bk) click to toggle source
     # File lib/sinatra/base.rb, line 846
846:       def delete(path, opts={}, &bk); route 'DELETE', path, opts, &bk end
development?() click to toggle source
     # File lib/sinatra/base.rb, line 922
922:       def development?; environment == :development end
get(path, opts={}, &block) click to toggle source

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
head(path, opts={}, &bk) click to toggle source
     # File lib/sinatra/base.rb, line 847
847:       def head(path, opts={}, &bk);   route 'HEAD',   path, opts, &bk end
helpers(*extensions, &block) click to toggle source

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
new(app=nil) click to toggle source
     # 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
new(*args, &bk) click to toggle source

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
post(path, opts={}, &bk) click to toggle source
     # File lib/sinatra/base.rb, line 845
845:       def post(path, opts={}, &bk);   route 'POST',   path, opts, &bk end
production?() click to toggle source
     # File lib/sinatra/base.rb, line 923
923:       def production?;  environment == :production  end
prototype() click to toggle source

The prototype instance used to process requests.

     # File lib/sinatra/base.rb, line 959
959:       def prototype
960:         @prototype ||= new
961:       end
put(path, opts={}, &bk) click to toggle source
     # File lib/sinatra/base.rb, line 844
844:       def put(path, opts={}, &bk);    route 'PUT',    path, opts, &bk end
register(*extensions, &block) click to toggle source
     # 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!(options={}) click to toggle source

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
test?() click to toggle source
     # File lib/sinatra/base.rb, line 924
924:       def test?;        environment == :test        end
use(middleware, *args, &block) click to toggle source

Use the specified Rack middleware

     # File lib/sinatra/base.rb, line 933
933:       def use(middleware, *args, &block)
934:         @prototype = nil
935:         @middleware << [middleware, args, block]
936:       end

Private Class Methods

after(&block) click to toggle source

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
before(&block) click to toggle source

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
compile(path) click to toggle source
     # 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
condition(&block) click to toggle source

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
detect_rack_handler() click to toggle source
     # 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
disable(*opts) click to toggle source

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
enable(*opts) click to toggle source

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
error(codes=Exception, &block) click to toggle source

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
extensions() click to toggle source

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
host_name(pattern) click to toggle source
     # File lib/sinatra/base.rb, line 802
802:       def host_name(pattern)
803:         condition { pattern === request.host }
804:       end
inherited(subclass) click to toggle source
     # File lib/sinatra/base.rb, line 995
995:       def inherited(subclass)
996:         subclass.reset!
997:         super
998:       end
inline_templates=(file=nil) click to toggle source

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
invoke_hook(name, *args) click to toggle source
     # 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
layout(name=:layout, &block) click to toggle source

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
metadef(message, &block) click to toggle source
      # 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() click to toggle source

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
mime_type(type, value=nil) click to toggle source

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
not_found(&block) click to toggle source

Sugar for `error(404) { … }`

     # File lib/sinatra/base.rb, line 731
731:       def not_found(&block)
732:         error 404, &block
733:       end
provides(*types) click to toggle source
     # 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
reset!() click to toggle source
     # 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
route(verb, path, options={}, &block) click to toggle source
     # 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
set(option, value=self, &block) click to toggle source

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
synchronize(&block) click to toggle source
      # 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
template(name, &block) click to toggle source

Define a named template. The block must return the template source.

     # File lib/sinatra/base.rb, line 736
736:       def template(name, &block)
737:         filename, line = caller_locations.first
738:         templates[name] = [block, filename, line.to_i]
739:       end
user_agent(pattern) click to toggle source
     # File lib/sinatra/base.rb, line 806
806:       def user_agent(pattern)
807:         condition {
808:           if request.user_agent =~ pattern
809:             @params[:agent] = $~[1..1]
810:             true
811:           else
812:             false
813:           end
814:         }
815:       end

Public Instance Methods

call(env) click to toggle source

Rack call interface.

     # File lib/sinatra/base.rb, line 398
398:     def call(env)
399:       dup.call!(env)
400:     end
call!(env) click to toggle source
     # 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() click to toggle source

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
halt(*response) click to toggle source

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
options() click to toggle source
Alias for: settings
pass(&block) click to toggle source

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
settings() click to toggle source

Access settings defined with Base.set.

     # File lib/sinatra/base.rb, line 428
428:     def settings
429:       self.class
430:     end
Also aliased as: options

Private Instance Methods

after_filter!(base=self.class) click to toggle source

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
before_filter!(base=self.class) click to toggle source

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!() click to toggle source

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
dump_errors!(boom) click to toggle source
     # 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
error_block!(*keys) click to toggle source

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
handle_exception!(boom) click to toggle source
     # 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
handle_not_found!(boom) click to toggle source
     # 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
indifferent_hash() click to toggle source
     # 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
indifferent_params(params) click to toggle source

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
invoke(&block) click to toggle source

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
route!(base=self.class, pass_block=nil) click to toggle source

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
route_eval(&block) click to toggle source

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
route_missing() click to toggle source

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
static!() click to toggle source

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.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.