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:

  • (Boolean)

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:

  • (Boolean)

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:

  • (Boolean)

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