まず読め
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に切り出すことは当たり前のティップスなので[要出典]、そういうときに少し便利かも。そうでもないか?
まとめ
まあ読め。