sinatra/sinatra-contrib/lib/sinatra/extension.rb

97 lines
2.5 KiB
Ruby

# frozen_string_literal: true
require 'sinatra/base'
module Sinatra
# = Sinatra::Extension
#
# <tt>Sinatra::Extension</tt> is a mixin that provides some syntactic sugar
# for your extensions. It allows you to call almost any
# <tt>Sinatra::Base</tt> method directly inside your extension
# module. This means you can use +get+ to define a route, +before+
# to define a before filter, +set+ to define a setting and so on.
#
# Is important to be aware that this mixin remembers the method calls you
# make, and then, when your extension is registered, replays them on the
# Sinatra application that has been extended. In order to do that, it
# defines a <tt>registered</tt> method, so, if your extension defines one
# too, remember to call +super+.
#
# == Usage
#
# Just require the mixin and extend your extension with it:
#
# require 'sinatra/extension'
#
# module MyExtension
# extend Sinatra::Extension
#
# # set some settings for development
# configure :development do
# set :reload_stuff, true
# end
#
# # define a route
# get '/' do
# 'Hello World'
# end
#
# # The rest of your extension code goes here...
# end
#
# You can also create an extension with the +new+ method:
#
# MyExtension = Sinatra::Extension.new do
# # Your extension code goes here...
# end
#
# This is useful when you just want to pass a block to
# <tt>Sinatra::Base.register</tt>.
module Extension
def self.new(&block)
ext = Module.new.extend(self)
ext.class_eval(&block)
ext
end
def settings
self
end
def configure(*args, &block)
record(:configure, *args) { |c| c.instance_exec(c, &block) }
end
def registered(base = nil, &block)
base ? replay(base) : record(:class_eval, &block)
end
private
def record(method, *args, &block)
recorded_methods << [method, args, block]
end
def replay(object)
recorded_methods.each { |m, a, b| object.send(m, *a, &b) }
end
def recorded_methods
@recorded_methods ||= []
end
def method_missing(method, *args, &block)
return super unless Sinatra::Base.respond_to? method
record(method, *args, &block)
DontCall.new(method)
end
class DontCall < BasicObject
def initialize(method) @method = method end
def method_missing(*) raise "not supposed to use result of #{@method}!" end
def inspect; "#<#{self.class}: #{@method}>" end
end
end
end