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 =
[
  /lib\/sinatra.*\.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



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

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

Class Attribute Details

.errorsObject (readonly)

Returns the value of attribute errors.



610
611
612
# File 'lib/sinatra/base.rb', line 610

def errors
  @errors
end

.filtersObject (readonly)

Returns the value of attribute filters.



610
611
612
# File 'lib/sinatra/base.rb', line 610

def filters
  @filters
end

.routesObject (readonly)

Returns the value of attribute routes.



610
611
612
# File 'lib/sinatra/base.rb', line 610

def routes
  @routes
end

.templatesObject (readonly)

Returns the value of attribute templates.



610
611
612
# File 'lib/sinatra/base.rb', line 610

def templates
  @templates
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



352
353
354
# File 'lib/sinatra/base.rb', line 352

def app
  @app
end

#envObject

Returns the value of attribute env.



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

def env
  @env
end

#paramsObject

Returns the value of attribute params.



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

def params
  @params
end

#requestObject

Returns the value of attribute request.



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

def request
  @request
end

#responseObject

Returns the value of attribute response.



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

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.



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

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

.call(env) ⇒ Object



914
915
916
# File 'lib/sinatra/base.rb', line 914

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.



963
964
965
966
# File 'lib/sinatra/base.rb', line 963

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

.caller_locationsObject



968
969
970
971
972
# File 'lib/sinatra/base.rb', line 968

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.



734
735
736
# File 'lib/sinatra/base.rb', line 734

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



865
866
867
# File 'lib/sinatra/base.rb', line 865

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

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



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

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

.development?Boolean

Returns:

  • (Boolean)


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

def development?; environment == :development end

.disable(*opts) ⇒ Object

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



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

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.



659
660
661
# File 'lib/sinatra/base.rb', line 659

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.



671
672
673
674
675
676
677
# File 'lib/sinatra/base.rb', line 671

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.



624
625
626
627
628
629
630
# File 'lib/sinatra/base.rb', line 624

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.



773
774
775
776
777
778
779
# File 'lib/sinatra/base.rb', line 773

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



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

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



845
846
847
848
# File 'lib/sinatra/base.rb', line 845

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.



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

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.



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

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.



633
634
635
636
637
638
639
# File 'lib/sinatra/base.rb', line 633

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.



902
903
904
905
906
907
908
909
910
911
912
# File 'lib/sinatra/base.rb', line 902

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) { ... }



680
681
682
# File 'lib/sinatra/base.rb', line 680

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

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



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

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

.production?Boolean

Returns:

  • (Boolean)


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

def production?;  environment == :production  end

.prototypeObject

The prototype instance used to process requests.



895
896
897
# File 'lib/sinatra/base.rb', line 895

def prototype
  @prototype ||= new
end

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



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

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

.register(*extensions, &block) ⇒ Object



850
851
852
853
854
855
856
857
# File 'lib/sinatra/base.rb', line 850

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



612
613
614
615
616
617
618
619
620
621
# File 'lib/sinatra/base.rb', line 612

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)



877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
# File 'lib/sinatra/base.rb', line 877

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
  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.



643
644
645
646
647
648
649
650
651
652
653
654
655
656
# File 'lib/sinatra/base.rb', line 643

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.



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

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

.test?Boolean

Returns:

  • (Boolean)


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

def test?;        environment == :test        end

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

Use the specified Rack middleware



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

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.



697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
# File 'lib/sinatra/base.rb', line 697

def use_in_file_templates!(file=nil)
  file ||= caller_files.first
  app, data =
    ::IO.read(file).split(/^__END__$/, 2) rescue nil

  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.



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

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

#call!(env) ⇒ Object



366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/sinatra/base.rb', line 366

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.



408
409
410
411
412
413
414
415
# File 'lib/sinatra/base.rb', line 408

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.



395
396
397
398
# File 'lib/sinatra/base.rb', line 395

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

#optionsObject

Access options defined with Base.set.



389
390
391
# File 'lib/sinatra/base.rb', line 389

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.



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

def pass
  throw :pass
end