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 =

:nodoc:

[ # :nodoc:
  /\/sinatra(\/(base|main|showexceptions))?\.rb$/, # all sinatra code
  /lib\/tilt.*\.rb$/,                              # all tilt code
  /^\(.*\)$/,                                      # generated code
  /rubygems\/custom_require\.rb$/,                 # rubygems require hacks
  /active_support/,                                # active_support require hacks
  /bundler(\/runtime)?\.rb/,                       # bundler require hacks
  /<internal:/,                                    # internal in ruby >= 1.9.2
  /src\/kernel\/bootstrap\/[A-Z]/                  # maglev kernel files
]

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Templates

#builder, #coffee, #creole, #erb, #erubis, #find_template, #haml, #less, #liquid, #markaby, #markdown, #nokogiri, #radius, #rdoc, #sass, #scss, #slim, #textile

Methods included from Helpers

#attachment, #back, #body, #cache_control, #client_error?, #content_type, #error, #etag, #expires, #headers, #informational?, #last_modified, #logger, #mime_type, #not_found, #not_found?, #redirect, #redirect?, #send_file, #server_error?, #session, #status, #stream, #success?, #time_for, #uri

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



746
747
748
749
750
751
# File 'lib/sinatra/base.rb', line 746

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

Class Attribute Details

.errorsObject (readonly)

Returns the value of attribute errors.



982
983
984
# File 'lib/sinatra/base.rb', line 982

def errors
  @errors
end

.filtersObject (readonly)

Returns the value of attribute filters.



982
983
984
# File 'lib/sinatra/base.rb', line 982

def filters
  @filters
end

.routesObject (readonly)

Returns the value of attribute routes.



982
983
984
# File 'lib/sinatra/base.rb', line 982

def routes
  @routes
end

.templatesObject (readonly)

Returns the value of attribute templates.



982
983
984
# File 'lib/sinatra/base.rb', line 982

def templates
  @templates
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



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

def app
  @app
end

#envObject

Returns the value of attribute env.



758
759
760
# File 'lib/sinatra/base.rb', line 758

def env
  @env
end

#paramsObject

Returns the value of attribute params.



758
759
760
# File 'lib/sinatra/base.rb', line 758

def params
  @params
end

#requestObject

Returns the value of attribute request.



758
759
760
# File 'lib/sinatra/base.rb', line 758

def request
  @request
end

#responseObject

Returns the value of attribute response.



758
759
760
# File 'lib/sinatra/base.rb', line 758

def response
  @response
end

#template_cacheObject (readonly)

Returns the value of attribute template_cache.



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

def template_cache
  @template_cache
end

Class Method Details

.add_filter(type, path = nil, options = {}, &block) ⇒ Object

add a filter



1157
1158
1159
1160
# File 'lib/sinatra/base.rb', line 1157

def add_filter(type, path = nil, options = {}, &block)
  path, options = //, path if path.respond_to?(:each_pair)
  filters[type] << compile!(type, path || //, block, options)
end

.after(path = nil, options = {}, &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.



1152
1153
1154
# File 'lib/sinatra/base.rb', line 1152

def after(path = nil, options = {}, &block)
  add_filter(:after, path, options, &block)
end

.before(path = nil, options = {}, &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.



1145
1146
1147
# File 'lib/sinatra/base.rb', line 1145

def before(path = nil, options = {}, &block)
  add_filter(:before, path, options, &block)
end

.build(builder, *args, &bk) ⇒ Object

Creates a Rack::Builder instance with all the middleware set up and an instance of this class as end point.



1381
1382
1383
1384
1385
1386
# File 'lib/sinatra/base.rb', line 1381

def build(builder, *args, &bk)
  setup_default_middleware builder
  setup_middleware builder
  builder.run new!(*args, &bk)
  builder
end

.call(env) ⇒ Object



1388
1389
1390
# File 'lib/sinatra/base.rb', line 1388

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.



1495
1496
1497
# File 'lib/sinatra/base.rb', line 1495

def caller_files
  cleaned_caller(1).flatten
end

.caller_locationsObject

Like caller_files, but containing Arrays rather than strings with the first element being the file, and the second being the line.



1501
1502
1503
# File 'lib/sinatra/base.rb', line 1501

def caller_locations
  cleaned_caller 2
end

.condition(name = "#{caller.first[/`.*'/]} condition", &block) ⇒ Object

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



1164
1165
1166
# File 'lib/sinatra/base.rb', line 1164

def condition(name = "#{caller.first[/`.*'/]} condition", &block)
  @conditions << generate_method(name, &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



1327
1328
1329
# File 'lib/sinatra/base.rb', line 1327

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

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



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

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

.development?Boolean

Returns:

  • (Boolean)


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

def development?; environment == :development end

.disable(*opts) ⇒ Object

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



1063
1064
1065
# File 'lib/sinatra/base.rb', line 1063

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.



1058
1059
1060
# File 'lib/sinatra/base.rb', line 1058

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

.error(*codes, &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.



1070
1071
1072
1073
1074
1075
# File 'lib/sinatra/base.rb', line 1070

def error(*codes, &block)
  args  = compile! "ERROR", //, block
  codes = codes.map { |c| Array(c) }.flatten
  codes << Exception if codes.empty?
  codes.each { |c| @errors[c] = args }
end

.extensionsObject

Extension modules registered on this class and all superclasses.



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

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.



1219
1220
1221
1222
1223
1224
1225
# File 'lib/sinatra/base.rb', line 1219

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



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

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



1305
1306
1307
1308
# File 'lib/sinatra/base.rb', line 1305

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.



1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
# File 'lib/sinatra/base.rb', line 1095

def inline_templates=(file=nil)
  file = (file.nil? || file == true) ? (caller_files.first || File.expand_path($0)) : file

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

  if data
    if app and app =~ /([^\n]*\n)?#[^\n]*coding: *(\S+)/m
      encoding = $2
    else
      encoding = settings.default_encoding
    end
    lines = app.count("\n") + 1
    template = nil
    force_encoding data, encoding
    data.each_line do |line|
      lines += 1
      if line =~ /^@@\s*(.*\S)\s*$/
        template = force_encoding('', encoding)
        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.



1089
1090
1091
# File 'lib/sinatra/base.rb', line 1089

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

.middlewareObject

Middleware used in this class and all superclasses.



1012
1013
1014
1015
1016
1017
1018
# File 'lib/sinatra/base.rb', line 1012

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.



1127
1128
1129
1130
1131
1132
# File 'lib/sinatra/base.rb', line 1127

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

.mime_types(type) ⇒ Object

provides all mime types matching type, including deprecated types:

mime_types :html # => ['text/html']
mime_types :js   # => ['application/javascript', 'text/javascript']


1137
1138
1139
1140
# File 'lib/sinatra/base.rb', line 1137

def mime_types(type)
  type = mime_type type
  type =~ /^application\/(xml|javascript)$/ ? [type, "text/#$1"] : [type]
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.



1375
1376
1377
# File 'lib/sinatra/base.rb', line 1375

def new(*args, &bk)
  build(Rack::Builder.new, *args, &bk).to_app
end

.not_found(&block) ⇒ Object

Sugar for ‘error(404) { … }`



1078
1079
1080
# File 'lib/sinatra/base.rb', line 1078

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

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



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

def options(path, opts={}, &bk) route 'OPTIONS', path, opts, &bk end

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



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

def patch(path, opts={}, &bk)   route 'PATCH',   path, opts, &bk end

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



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

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

.production?Boolean

Returns:

  • (Boolean)


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

def production?;  environment == :production  end

.prototypeObject

The prototype instance used to process requests.



1365
1366
1367
# File 'lib/sinatra/base.rb', line 1365

def prototype
  @prototype ||= new
end

.public=(value) ⇒ Object



1168
1169
1170
1171
# File 'lib/sinatra/base.rb', line 1168

def public=(value)
  warn ":public is no longer used to avoid overloading Module#public, use :public_folder instead"
  set(:public_folder, value)
end

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



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

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

.quit!(server, handler_name) ⇒ Object



1337
1338
1339
1340
1341
# File 'lib/sinatra/base.rb', line 1337

def quit!(server, handler_name)
  # Use Thin's hard #stop! if available, otherwise just #stop.
  server.respond_to?(:stop!) ? server.stop! : server.stop
  $stderr.puts "\n== Sinatra has ended his set (crowd applauds)" unless handler_name =~/cgi/i
end

.register(*extensions, &block) ⇒ Object

Register an extension. Alternatively take a block from which an extension will be created and registered on the fly.



1312
1313
1314
1315
1316
1317
1318
1319
# File 'lib/sinatra/base.rb', line 1312

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

Removes all routes, filters, middleware and extension hooks from the current class (not routes/filters/… defined by its superclass).



986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# File 'lib/sinatra/base.rb', line 986

def reset!
  @conditions     = []
  @routes         = {}
  @filters        = {:before => [], :after => []}
  @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). If given a block, will call with the constructed handler once we have taken the stage.



1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
# File 'lib/sinatra/base.rb', line 1346

def run!(options={})
  set options
  handler      = detect_rack_handler
  handler_name = handler.name.gsub(/.*::/, '')
  handler.run self, :Host => bind, :Port => port do |server|
    unless handler_name =~ /cgi/i
      $stderr.puts "== Sinatra/#{Sinatra::VERSION} has taken the stage " +
      "on #{port} for #{environment} with backup from #{handler_name}"
    end
    [:INT, :TERM].each { |sig| trap(sig) { quit!(server, handler_name) } }
    server.threaded = settings.threaded if server.respond_to? :threaded=
    set :running, true
    yield server if block_given?
  end
rescue Errno::EADDRINUSE
  $stderr.puts "== Someone is already performing on port #{port}!"
end

.set(option, value = (not_set = true), ignore_setter = false, &block) ⇒ 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.

Raises:

  • (ArgumentError)


1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
# File 'lib/sinatra/base.rb', line 1022

def set(option, value = (not_set = true), ignore_setter = false, &block)
  raise ArgumentError if block and !not_set
  value, not_set = block, false if block

  if not_set
    raise ArgumentError unless option.respond_to?(:each)
    option.each { |k,v| set(k, v) }
    return self
  end

  if respond_to?("#{option}=") and not ignore_setter
    return __send__("#{option}=", value)
  end

  setter = proc { |val| set option, val, true }
  getter = proc { value }

  case value
  when Proc
    getter = value
  when Symbol, Fixnum, FalseClass, TrueClass, NilClass
    getter = value.inspect
  when Hash
    setter = proc do |val|
      val = value.merge val if Hash === val
      set option, val, true
    end
  end

  define_singleton_method("#{option}=", setter) if setter
  define_singleton_method(option, getter) if getter
  define_singleton_method("#{option}?", "!!#{option}") unless method_defined? "#{option}?"
  self
end

.settingsObject

Access settings defined with Base.set.



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

def self.settings
  self
end

.template(name, &block) ⇒ Object

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



1083
1084
1085
1086
# File 'lib/sinatra/base.rb', line 1083

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

.test?Boolean

Returns:

  • (Boolean)


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

def test?;        environment == :test        end

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

Use the specified Rack middleware



1332
1333
1334
1335
# File 'lib/sinatra/base.rb', line 1332

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

Instance Method Details

#call(env) ⇒ Object

Rack call interface.



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

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

#call!(env) ⇒ Object

:nodoc:



760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
# File 'lib/sinatra/base.rb', line 760

def call!(env) # :nodoc:
  @env      = env
  @request  = Request.new(env)
  @response = Response.new
  @params   = indifferent_params(@request.params)
  template_cache.clear if settings.reload_templates
  force_encoding(@params)

  @response['Content-Type'] = nil
  invoke { dispatch! }
  invoke { error_block!(response.status) }

  unless @response['Content-Type']
    if Array === body and body[0].respond_to? :content_type
      content_type body[0].content_type
    else
      content_type :html
    end
  end

  @response.finish
end

#forwardObject

Forward the request to the downstream app – middleware only.



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

def forward
  fail "downstream app not set" unless @app.respond_to? :call
  status, headers, body = @app.call 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.



801
802
803
804
# File 'lib/sinatra/base.rb', line 801

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

#new!Object

Create a new instance without middleware in front of it.



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

alias new! new

#optionsObject



793
794
795
796
797
# File 'lib/sinatra/base.rb', line 793

def options
  warn "Sinatra::Base#options is deprecated and will be removed, " \
    "use #settings instead."
  settings
end

#pass(&block) ⇒ Object

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



809
810
811
# File 'lib/sinatra/base.rb', line 809

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

#settingsObject

Access settings defined with Base.set.



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

def settings
  self.class.settings
end