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

Application

Constant Summary collapse

CALLERS_TO_IGNORE =
[
  /\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra 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, #haml, #sass

Methods included from Helpers

#attachment, #back, #body, #content_type, #error, #etag, #headers, #last_modified, #media_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



358
359
360
361
# File 'lib/sinatra/base.rb', line 358

def initialize(app=nil)
  @app = app
  yield self if block_given?
end

Class Attribute Details

.errorsObject (readonly)

Returns the value of attribute errors.



614
615
616
# File 'lib/sinatra/base.rb', line 614

def errors
  @errors
end

.filtersObject (readonly)

Returns the value of attribute filters.



614
615
616
# File 'lib/sinatra/base.rb', line 614

def filters
  @filters
end

.routesObject (readonly)

Returns the value of attribute routes.



614
615
616
# File 'lib/sinatra/base.rb', line 614

def routes
  @routes
end

.templatesObject (readonly)

Returns the value of attribute templates.



614
615
616
# File 'lib/sinatra/base.rb', line 614

def templates
  @templates
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



356
357
358
# File 'lib/sinatra/base.rb', line 356

def app
  @app
end

#envObject

Returns the value of attribute env.



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

def env
  @env
end

#paramsObject

Returns the value of attribute params.



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

def params
  @params
end

#requestObject

Returns the value of attribute request.



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

def request
  @request
end

#responseObject

Returns the value of attribute response.



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

def response
  @response
end

Class Method Details

.before(&block) ⇒ Object

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



737
738
739
# File 'lib/sinatra/base.rb', line 737

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

.call(env) ⇒ Object



924
925
926
# File 'lib/sinatra/base.rb', line 924

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.



973
974
975
976
# File 'lib/sinatra/base.rb', line 973

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

.caller_locationsObject



978
979
980
981
982
# File 'lib/sinatra/base.rb', line 978

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.



743
744
745
# File 'lib/sinatra/base.rb', line 743

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



874
875
876
# File 'lib/sinatra/base.rb', line 874

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

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



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

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

.development?Boolean

Returns:

  • (Boolean)


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

def development?; environment == :development end

.disable(*opts) ⇒ Object

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



668
669
670
# File 'lib/sinatra/base.rb', line 668

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.



663
664
665
# File 'lib/sinatra/base.rb', line 663

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.



675
676
677
678
679
680
681
# File 'lib/sinatra/base.rb', line 675

def error(codes=Exception, &block)
  if codes.respond_to? :each
    codes.each { |err| error(err, &block) }
  else
    @errors[codes] = block
  end
end

.extensionsObject

Extension modules registered on this class and all superclasses.



628
629
630
631
632
633
634
# File 'lib/sinatra/base.rb', line 628

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.



782
783
784
785
786
787
788
# File 'lib/sinatra/base.rb', line 782

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



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

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



854
855
856
857
# File 'lib/sinatra/base.rb', line 854

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

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

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



695
696
697
# File 'lib/sinatra/base.rb', line 695

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

.media_type(type) ⇒ Object

Look up a media type by file extension in Rack’s mime registry.



728
729
730
731
732
# File 'lib/sinatra/base.rb', line 728

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

.middlewareObject

Middleware used in this class and all superclasses.



637
638
639
640
641
642
643
# File 'lib/sinatra/base.rb', line 637

def middleware
  if superclass.respond_to?(:middleware)
    superclass.middleware + @middleware
  else
    @middleware
  end
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.



912
913
914
915
916
917
918
919
920
921
922
# File 'lib/sinatra/base.rb', line 912

def new(*args, &bk)
  builder = Rack::Builder.new
  builder.use Rack::Session::Cookie if sessions? && !test?
  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) { … }`



684
685
686
# File 'lib/sinatra/base.rb', line 684

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

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



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

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

.production?Boolean

Returns:

  • (Boolean)


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

def production?;  environment == :production  end

.prototypeObject

The prototype instance used to process requests.



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

def prototype
  @prototype ||= new
end

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



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

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

.register(*extensions, &block) ⇒ Object



859
860
861
862
863
864
865
866
# File 'lib/sinatra/base.rb', line 859

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



616
617
618
619
620
621
622
623
624
625
# File 'lib/sinatra/base.rb', line 616

def reset!
  @conditions = []
  @routes     = {}
  @filters    = []
  @templates  = {}
  @errors     = {}
  @middleware = []
  @prototype  = nil
  @extensions = []
end

.run!(options = {}) ⇒ Object

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



886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
# File 'lib/sinatra/base.rb', line 886

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.



647
648
649
650
651
652
653
654
655
656
657
658
659
660
# File 'lib/sinatra/base.rb', line 647

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.



689
690
691
692
# File 'lib/sinatra/base.rb', line 689

def template(name, &block)
  filename, line = caller_locations.first
  templates[name] = { :filename => filename, :line => line, :template => block }
end

.test?Boolean

Returns:

  • (Boolean)


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

def test?;        environment == :test        end

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

Use the specified Rack middleware



879
880
881
882
# File 'lib/sinatra/base.rb', line 879

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

.use_in_file_templates!(file = nil) ⇒ Object

Load embeded templates from the file; uses the caller’s __FILE__ when no file is specified.



701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
# File 'lib/sinatra/base.rb', line 701

def use_in_file_templates!(file=nil)
  file ||= caller_files.first

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

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

Instance Method Details

#call(env) ⇒ Object

Rack call interface.



364
365
366
# File 'lib/sinatra/base.rb', line 364

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

#call!(env) ⇒ Object



370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/sinatra/base.rb', line 370

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.



412
413
414
415
416
417
418
419
# File 'lib/sinatra/base.rb', line 412

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.



399
400
401
402
# File 'lib/sinatra/base.rb', line 399

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

#optionsObject

Access options defined with Base.set.



393
394
395
# File 'lib/sinatra/base.rb', line 393

def options
  self.class
end

#passObject

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



407
408
409
# File 'lib/sinatra/base.rb', line 407

def pass
  throw :pass
end