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
]

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Templates

#builder, #coffee, #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, #content_type, #error, #etag, #expires, #headers, #last_modified, #mime_type, #not_found, #redirect, #send_file, #session, #status, #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



621
622
623
624
625
# File 'lib/sinatra/base.rb', line 621

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

Class Attribute Details

.errorsObject (readonly)

Returns the value of attribute errors.



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

def errors
  @errors
end

.filtersObject (readonly)

Returns the value of attribute filters.



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

def filters
  @filters
end

.routesObject (readonly)

Returns the value of attribute routes.



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

def routes
  @routes
end

.templatesObject (readonly)

Returns the value of attribute templates.



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

def templates
  @templates
end

Instance Attribute Details

#appObject

Returns the value of attribute app.



618
619
620
# File 'lib/sinatra/base.rb', line 618

def app
  @app
end

#envObject

Returns the value of attribute env.



632
633
634
# File 'lib/sinatra/base.rb', line 632

def env
  @env
end

#paramsObject

Returns the value of attribute params.



632
633
634
# File 'lib/sinatra/base.rb', line 632

def params
  @params
end

#requestObject

Returns the value of attribute request.



632
633
634
# File 'lib/sinatra/base.rb', line 632

def request
  @request
end

#responseObject

Returns the value of attribute response.



632
633
634
# File 'lib/sinatra/base.rb', line 632

def response
  @response
end

#template_cacheObject (readonly)

Returns the value of attribute template_cache.



619
620
621
# File 'lib/sinatra/base.rb', line 619

def template_cache
  @template_cache
end

Class Method Details

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

add a filter



1057
1058
1059
1060
1061
1062
1063
1064
# File 'lib/sinatra/base.rb', line 1057

def add_filter(type, path = nil, options = {}, &block)
  return filters[type] << block unless path
  path, options = //, path if path.respond_to?(:each_pair)
  block, *arguments = compile!(type, path, block, options)
  add_filter(type) do
    process_route(*arguments) { instance_eval(&block) }
  end
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.



1052
1053
1054
# File 'lib/sinatra/base.rb', line 1052

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.



1045
1046
1047
# File 'lib/sinatra/base.rb', line 1045

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

.build(*args, &bk) ⇒ Object

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



1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
# File 'lib/sinatra/base.rb', line 1259

def build(*args, &bk)
  builder = Rack::Builder.new
  builder.use Rack::MethodOverride if method_override?
  builder.use ShowExceptions       if show_exceptions?
  builder.use Rack::CommonLogger   if logging?
  builder.use Rack::Head
  setup_sessions builder
  middleware.each { |c,a,b| builder.use(c, *a, &b) }
  builder.run new!(*args, &bk)
  builder
end

.call(env) ⇒ Object



1271
1272
1273
# File 'lib/sinatra/base.rb', line 1271

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.



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

def caller_files
  caller_locations.
    map { |file,line| file }
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.



1335
1336
1337
1338
1339
# File 'lib/sinatra/base.rb', line 1335

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.



1068
1069
1070
# File 'lib/sinatra/base.rb', line 1068

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



1210
1211
1212
# File 'lib/sinatra/base.rb', line 1210

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

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



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

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

.development?Boolean

Returns:

  • (Boolean)


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

def development?; environment == :development end

.disable(*opts) ⇒ Object

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



966
967
968
# File 'lib/sinatra/base.rb', line 966

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.



961
962
963
# File 'lib/sinatra/base.rb', line 961

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.



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

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

.extensionsObject

Extension modules registered on this class and all superclasses.



923
924
925
926
927
928
929
# File 'lib/sinatra/base.rb', line 923

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.



1109
1110
1111
1112
1113
1114
1115
# File 'lib/sinatra/base.rb', line 1109

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



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

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



1188
1189
1190
1191
# File 'lib/sinatra/base.rb', line 1188

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.



995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
# File 'lib/sinatra/base.rb', line 995

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.



989
990
991
# File 'lib/sinatra/base.rb', line 989

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

.middlewareObject

Middleware used in this class and all superclasses.



932
933
934
935
936
937
938
# File 'lib/sinatra/base.rb', line 932

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.



1027
1028
1029
1030
1031
1032
# File 'lib/sinatra/base.rb', line 1027

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']


1037
1038
1039
1040
# File 'lib/sinatra/base.rb', line 1037

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.



1253
1254
1255
# File 'lib/sinatra/base.rb', line 1253

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

.not_found(&block) ⇒ Object

Sugar for ‘error(404) { … }`



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

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

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



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

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

.production?Boolean

Returns:

  • (Boolean)


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

def production?;  environment == :production  end

.prototypeObject

The prototype instance used to process requests.



1243
1244
1245
# File 'lib/sinatra/base.rb', line 1243

def prototype
  @prototype ||= new
end

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



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

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

.quit!(server, handler_name) ⇒ Object



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

def quit!(server, handler_name)
  # Use Thin's 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

.register(*extensions, &block) ⇒ Object

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



1195
1196
1197
1198
1199
1200
1201
1202
# File 'lib/sinatra/base.rb', line 1195

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



906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
# File 'lib/sinatra/base.rb', line 906

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)



1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
# File 'lib/sinatra/base.rb', line 1228

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 => bind, :Port => port do |server|
    [:INT, :TERM].each { |sig| trap(sig) { quit!(server, handler_name) } }
    set :running, true
  end
rescue Errno::EADDRINUSE => e
  puts "== Someone is already performing on port #{port}!"
end

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


942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
# File 'lib/sinatra/base.rb', line 942

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

.settingsObject Also known as: options

Access settings defined with Base.set.



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

def self.settings
  self
end

.template(name, &block) ⇒ Object

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



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

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

.test?Boolean

Returns:

  • (Boolean)


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

def test?;        environment == :test        end

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

Use the specified Rack middleware



1215
1216
1217
1218
# File 'lib/sinatra/base.rb', line 1215

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

Instance Method Details

#call(env) ⇒ Object

Rack call interface.



628
629
630
# File 'lib/sinatra/base.rb', line 628

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

#call!(env) ⇒ Object

:nodoc:



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

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(@request.route)
  force_encoding(@params)

  @response['Content-Type'] = nil
  invoke { dispatch! }
  invoke { error_block!(response.status) }
  unless @response['Content-Type']
    if body.respond_to?(:to_ary) and body.first.respond_to? :content_type
      content_type body.first.content_type
    else
      content_type :html
    end
  end

  @response.finish
end

#forwardObject

Forward the request to the downstream app – middleware only.



687
688
689
690
691
692
693
694
# File 'lib/sinatra/base.rb', line 687

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.



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

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.



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

alias new! new

#pass(&block) ⇒ Object

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



682
683
684
# File 'lib/sinatra/base.rb', line 682

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

#settingsObject Also known as: options

Access settings defined with Base.set.



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

def settings
  self.class.settings
end