まず読め
Sinatra::Baseを直接いじるな。あらゆるSinatraアプリケーションに影響があってきついので、ことモジュラースタイルでは明示的にregisterさせること- Extension内部で直接
require 'sinatra'するとモジュラスタイルでサーバが立ち上がり沢山の悲しみが生まれるので、require 'sinatra/base'しなさい- http://www.sinatrarb.com/extensions.html に書いてあるAPIだけをできるだけ使え。直接Sinatraのコアクラスにモンキーパッチとかは勘弁
- Extensionは
Sinatraのnamespace配下で、moduleとして定義される べきだ 。例えば、基本認証を有効にするようなやつならSinatra::BasicAuth
なるべくコアクラスと隔離された形で書くのが望ましい。
クラシックでもモジュラーでも使えるようにするには
Sinatra.helpers
require 'sinatra/base'
module Sinatra
module HTMLEscapeHelper
def h(text)
Rack::Utils.escape_html(text)
end
end
helpers HTMLEscapeHelper
end
ヘルパーならこんな感じで定義する。
これで、クラシックの時は暗示的に、モジュラーな時は明示的にhelpersで利用宣言、という風にできる
Sinatra.register
↑と同様ですね。
require 'sinatra/base'
module Sinatra
module LinkBlocker
def block_links_from(host)
before {
halt 403, "Go Away!" if request.referer.match(host)
}
end
end
register LinkBlocker
end
なお、クラシックSinatraの場合、Sinatra.registerでクラシックでの利用を宣言したら、一緒にトップレベルにメソッドが生える。
この辺のトップレベルにメソッドが生える仕組みは、 Sinatra::Delegator.delegate というメソッドが握っている。
この辺りの処理の通り。
Sinatra向けクラスマクロ
モジュールに普通に定義したメソッドはそのままクラスマクロになる。要するに、内部で、 extend してるんですね。
このクラスマクロ内部で普通に get とか呼んじゃっていいんでよしなにしてください。
あと、ゲッター、セッター系は特殊な扱いになる。詳細は書いてます。
self.registered
register されたときに呼ばれる挙動を定義する。self.includedなどと同じノリで書く。
def self.registered(base)
base.set :foo, "BAR"
end
このマクロ感が大事な気がする。
Extensionを書くのに便利なライブラリ
sinatra-contrib にある。
module MyExtension
extend Sinatra::Extension
configure :development do
set :reload_stuff, true
end
get '/' do
'Hello World'
end
end
こうでもいい
module MyExtension
extend Sinatra::Extension
registered do
configure :development do
set :reload_stuff, true
end
end
end
少し大きなSinatraアプリケーションなら、設定やヘルパーなどをExtensionに切り出すことは当たり前のティップスなので[要出典]、そういうときに少し便利かも。そうでもないか?
まとめ
まあ読め。