Class: Sinatra::Base

Inherits:
Object
  • Object
show all
Includes:
Rack::Utils, Helpers, Templates
Defined in:
lib/sinatra/base.rb

Overview

Base class for all Sinatra applications and middleware.

Direct Known Subclasses

Default

Constant Summary collapse

CALLERS_TO_IGNORE =
[
  /\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra code
  /lib\/tilt.*\.rb$/,    # all tilt code
  /\(.*\)/,              # generated code
  /custom_require\.rb$/, # rubygems require hacks
  /active_support/,      # active_support require hacks
]

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Templates

#builder, #erb, #erubis, #haml, #sass

Methods included from Helpers

#attachment, #back, #body, #cache_control, #content_type, #error, #etag, #expires, #headers, #last_modified, #mime_type, #not_found, #redirect, #send_file, #session, #status

Constructor Details

#initialize(app = nil) {|_self| ... } ⇒ Base

Returns a new instance of Base.

Yields:

  • (_self)

Yield Parameters:

  • _self (Sinatra::Base)

    the object that the method was called on



368
369
370
371
372
# File 'lib/sinatra/base.rb', line 368

def initialize(app=nil)
  @app = app
  @template_cache = Tilt::Cache.new
  yield self if block_given?
end

Class Attribute Details

.after_filtersObject (readonly)

Returns the value of attribute after_filters.



637
638
639
# File 'lib/sinatra/base.rb', line 637

def after_filters
  @after_filters
end

.before_filtersObject (readonly)

Returns the value of attribute before_filters.



637
638
639
# File 'lib/sinatra/base.rb', line 637

def before_filters
  @before_filters
end

.errorsObject (readonly)

Returns the value of attribute errors.



637
638
639
# File 'lib/sinatra/base.rb', line 637

def errors
  @errors
end

.routesObject (readonly)

Returns the value of attribute routes.



637
638
639
# File 'lib/sinatra/base.rb', line 637

def routes
  @routes
end

.templatesObject (readonly)

Returns the value of attribute templates.



637
638
639
# File 'lib/sinatra/base.rb', line 637

def templates
  @templates
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



366
367
368
# File 'lib/sinatra/base.rb', line 366

def app
  @app
end

#envObject

Returns the value of attribute env.



379
380
381
# File 'lib/sinatra/base.rb', line 379

def env
  @env
end

#paramsObject

Returns the value of attribute params.



379
380
381
# File 'lib/sinatra/base.rb', line 379

def params
  @params
end

#requestObject

Returns the value of attribute request.



379
380
381
# File 'lib/sinatra/base.rb', line 379

def request
  @request
end

#responseObject

Returns the value of attribute response.



379
380
381
# File 'lib/sinatra/base.rb', line 379

def response
  @response
end

Class Method Details

.after(&block) ⇒ Object

Define an after filter; runs after all requests within the same context as route handlers and may access/modify the request and response.



769
770
771
# File 'lib/sinatra/base.rb', line 769

def after(&block)
  @after_filters << block
end

.before(&block) ⇒ Object

Define a before filter; runs before all requests within the same context as route handlers and may access/modify the request and response.



762
763
764
# File 'lib/sinatra/base.rb', line 762

def before(&block)
  @before_filters << block
end

.call(env) ⇒ Object



956
957
958
# File 'lib/sinatra/base.rb', line 956

def call(env)
  synchronize { prototype.call(env) }
end

.caller_filesObject

Like Kernel#caller but excluding certain magic entries and without line / method information; the resulting array contains filenames only.



1006
1007
1008
1009
# File 'lib/sinatra/base.rb', line 1006

def caller_files
  caller_locations.
    map { |file,line| file }
end

.caller_locationsObject



1011
1012
1013
1014
1015
# File 'lib/sinatra/base.rb', line 1011

def caller_locations
  caller(1).
    map    { |line| line.split(/:(?=\d|in )/)[0,2] }.
    reject { |file,line| CALLERS_TO_IGNORE.any? { |pattern| file =~ pattern } }
end

.condition(&block) ⇒ Object

Add a route condition. The route is considered non-matching when the block returns false.



775
776
777
# File 'lib/sinatra/base.rb', line 775

def condition(&block)
  @conditions << block
end

.configure(*envs) {|_self| ... } ⇒ Object

Set configuration options for Sinatra and/or the app. Allows scoping of settings for certain environments.

Yields:

  • (_self)

Yield Parameters:

  • _self (Sinatra::Base)

    the object that the method was called on



906
907
908
# File 'lib/sinatra/base.rb', line 906

def configure(*envs, &block)
  yield self if envs.empty? || envs.include?(environment.to_sym)
end

.delete(path, opts = {}, &bk) ⇒ Object



824
# File 'lib/sinatra/base.rb', line 824

def delete(path, opts={}, &bk); route 'DELETE', path, opts, &bk end

.development?Boolean

Returns:



900
# File 'lib/sinatra/base.rb', line 900

def development?; environment == :development end

.disable(*opts) ⇒ Object

Same as calling set :option, false for each of the given options.



697
698
699
# File 'lib/sinatra/base.rb', line 697

def disable(*opts)
  opts.each { |key| set(key, false) }
end

.enable(*opts) ⇒ Object

Same as calling set :option, true for each of the given options.



692
693
694
# File 'lib/sinatra/base.rb', line 692

def enable(*opts)
  opts.each { |key| set(key, true) }
end

.error(codes = Exception, &block) ⇒ Object

Define a custom error handler. Optionally takes either an Exception class, or an HTTP status code to specify which errors should be handled.



704
705
706
# File 'lib/sinatra/base.rb', line 704

def error(codes=Exception, &block)
  Array(codes).each { |code| @errors[code] = block }
end

.extensionsObject

Extension modules registered on this class and all superclasses.



657
658
659
660
661
662
663
# File 'lib/sinatra/base.rb', line 657

def extensions
  if superclass.respond_to?(:extensions)
    (@extensions + superclass.extensions).uniq
  else
    @extensions
  end
end

.get(path, opts = {}, &block) ⇒ Object

Defining a GET handler also automatically defines a HEAD handler.



814
815
816
817
818
819
820
# File 'lib/sinatra/base.rb', line 814

def get(path, opts={}, &block)
  conditions = @conditions.dup
  route('GET', path, opts, &block)

  @conditions = conditions
  route('HEAD', path, opts, &block)
end

.head(path, opts = {}, &bk) ⇒ Object



825
# File 'lib/sinatra/base.rb', line 825

def head(path, opts={}, &bk);   route 'HEAD',   path, opts, &bk end

.helpers(*extensions, &block) ⇒ Object

Makes the methods defined in the block and in the Modules given in extensions available to the handlers and templates



886
887
888
889
# File 'lib/sinatra/base.rb', line 886

def helpers(*extensions, &block)
  class_eval(&block)  if block_given?
  include(*extensions) if extensions.any?
end

.inline_templates=(file = nil) ⇒ Object

Load embeded templates from the file; uses the caller's FILE when no file is specified.



726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
# File 'lib/sinatra/base.rb', line 726

def inline_templates=(file=nil)
  file = (file.nil? || file == true) ? caller_files.first : file

  begin
    app, data =
      ::IO.read(file).gsub("\r\n", "\n").split(/^__END__$/, 2)
  rescue Errno::ENOENT
    app, data = nil
  end

  if data
    lines = app.count("\n") + 1
    template = nil
    data.each_line do |line|
      lines += 1
      if line =~ /^@@\s*(.*)/
        template = ''
        templates[$1.to_sym] = [template, file, lines]
      elsif template
        template << line
      end
    end
  end
end

.layout(name = :layout, &block) ⇒ Object

Define the layout template. The block must return the template source.



720
721
722
# File 'lib/sinatra/base.rb', line 720

def layout(name=:layout, &block)
  template name, &block
end

.middlewareObject

Middleware used in this class and all superclasses.



666
667
668
669
670
671
672
# File 'lib/sinatra/base.rb', line 666

def middleware
  if superclass.respond_to?(:middleware)
    superclass.middleware + @middleware
  else
    @middleware
  end
end

.mime_type(type, value = nil) ⇒ Object

Lookup or register a mime type in Rack's mime registry.



752
753
754
755
756
757
# File 'lib/sinatra/base.rb', line 752

def mime_type(type, value=nil)
  return type if type.nil? || type.to_s.include?('/')
  type = ".#{type}" unless type.to_s[0] == ?.
  return Rack::Mime.mime_type(type, nil) unless value
  Rack::Mime::MIME_TYPES[type] = value
end

.new(*args, &bk) ⇒ Object

Create a new instance of the class fronted by its middleware pipeline. The object is guaranteed to respond to #call but may not be an instance of the class new was called on.



944
945
946
947
948
949
950
951
952
953
954
# File 'lib/sinatra/base.rb', line 944

def new(*args, &bk)
  builder = Rack::Builder.new
  builder.use Rack::Session::Cookie if sessions?
  builder.use Rack::CommonLogger    if logging?
  builder.use Rack::MethodOverride  if methodoverride?
  builder.use ShowExceptions        if show_exceptions?
  middleware.each { |c,a,b| builder.use(c, *a, &b) }

  builder.run super
  builder.to_app
end

.not_found(&block) ⇒ Object

Sugar for error(404) { ... }



709
710
711
# File 'lib/sinatra/base.rb', line 709

def not_found(&block)
  error 404, &block
end

.post(path, opts = {}, &bk) ⇒ Object



823
# File 'lib/sinatra/base.rb', line 823

def post(path, opts={}, &bk);   route 'POST',   path, opts, &bk end

.production?Boolean

Returns:



901
# File 'lib/sinatra/base.rb', line 901

def production?;  environment == :production  end

.prototypeObject

The prototype instance used to process requests.



937
938
939
# File 'lib/sinatra/base.rb', line 937

def prototype
  @prototype ||= new
end

.put(path, opts = {}, &bk) ⇒ Object



822
# File 'lib/sinatra/base.rb', line 822

def put(path, opts={}, &bk);    route 'PUT',    path, opts, &bk end

.register(*extensions, &block) ⇒ Object



891
892
893
894
895
896
897
898
# File 'lib/sinatra/base.rb', line 891

def register(*extensions, &block)
  extensions << Module.new(&block) if block_given?
  @extensions += extensions
  extensions.each do |extension|
    extend extension
    extension.registered(self) if extension.respond_to?(:registered)
  end
end

.reset!Object



639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
# File 'lib/sinatra/base.rb', line 639

def reset!
  @conditions     = []
  @routes         = {}
  @before_filters = []
  @after_filters  = []
  @errors         = {}
  @middleware     = []
  @prototype      = nil
  @extensions     = []

  if superclass.respond_to?(:templates)
    @templates = Hash.new { |hash,key| superclass.templates[key] }
  else
    @templates = {}
  end
end

.run!(options = {}) ⇒ Object

Run the Sinatra app as a self-hosted server using Thin, Mongrel or WEBrick (in that order)



918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
# File 'lib/sinatra/base.rb', line 918

def run!(options={})
  set options
  handler      = detect_rack_handler
  handler_name = handler.name.gsub(/.*::/, '')
  puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
    "on #{port} for #{environment} with backup from #{handler_name}" unless handler_name =~/cgi/i
  handler.run self, :Host => host, :Port => port do |server|
    trap(:INT) do
      ## Use thins' hard #stop! if available, otherwise just #stop
      server.respond_to?(:stop!) ? server.stop! : server.stop
      puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
    end
    set :running, true
  end
rescue Errno::EADDRINUSE => e
  puts "== Someone is already performing on port #{port}!"
end

.set(option, value = self) ⇒ Object

Sets an option to the given value. If the value is a proc, the proc will be called every time the option is accessed.



676
677
678
679
680
681
682
683
684
685
686
687
688
689
# File 'lib/sinatra/base.rb', line 676

def set(option, value=self)
  if value.kind_of?(Proc)
    metadef(option, &value)
    metadef("#{option}?") { !!__send__(option) }
    metadef("#{option}=") { |val| set(option, Proc.new{val}) }
  elsif value == self && option.respond_to?(:to_hash)
    option.to_hash.each { |k,v| set(k, v) }
  elsif respond_to?("#{option}=")
    __send__ "#{option}=", value
  else
    set option, Proc.new{value}
  end
  self
end

.template(name, &block) ⇒ Object

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



714
715
716
717
# File 'lib/sinatra/base.rb', line 714

def template(name, &block)
  filename, line = caller_locations.first
  templates[name] = [block, filename, line.to_i]
end

.test?Boolean

Returns:



902
# File 'lib/sinatra/base.rb', line 902

def test?;        environment == :test        end

.use(middleware, *args, &block) ⇒ Object

Use the specified Rack middleware



911
912
913
914
# File 'lib/sinatra/base.rb', line 911

def use(middleware, *args, &block)
  @prototype = nil
  @middleware << [middleware, args, block]
end

Instance Method Details

#call(env) ⇒ Object

Rack call interface.



375
376
377
# File 'lib/sinatra/base.rb', line 375

def call(env)
  dup.call!(env)
end

#call!(env) ⇒ Object



381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/sinatra/base.rb', line 381

def call!(env)
  @env      = env
  @request  = Request.new(env)
  @response = Response.new
  @params   = indifferent_params(@request.params)

  invoke { dispatch! }
  invoke { error_block!(response.status) }

  status, header, body = @response.finish

  # Never produce a body on HEAD requests. Do retain the Content-Length
  # unless it's "0", in which case we assume it was calculated erroneously
  # for a manual HEAD response and remove it entirely.
  if @env['REQUEST_METHOD'] == 'HEAD'
    body = []
    header.delete('Content-Length') if header['Content-Length'] == '0'
  end

  [status, header, body]
end

#forwardObject

Forward the request to the downstream app -- middleware only.



424
425
426
427
428
429
430
431
# File 'lib/sinatra/base.rb', line 424

def forward
  fail "downstream app not set" unless @app.respond_to? :call
  status, headers, body = @app.call(@request.env)
  @response.status = status
  @response.body = body
  @response.headers.merge! headers
  nil
end

#halt(*response) ⇒ Object

Exit the current block, halts any further processing of the request, and returns the specified response.



411
412
413
414
# File 'lib/sinatra/base.rb', line 411

def halt(*response)
  response = response.first if response.length == 1
  throw :halt, response
end

#pass(&block) ⇒ Object

Pass control to the next matching route. If there are no more matching routes, Sinatra will return a 404 response.



419
420
421
# File 'lib/sinatra/base.rb', line 419

def pass(&block)
  throw :pass, block
end

#settingsObject Also known as: options

Access settings defined with Base.set.



404
405
406
# File 'lib/sinatra/base.rb', line 404

def settings
  self.class
end