概要
Sinatra のルーティングをクラスとして定義する方法を紹介します
Sinatra::Base を使うのは当然なのですがルーティングの定義などもすべてインスタンスメソッドとして定義します
環境
- macOS 11.7.6
- Ruby 3.2.1
- sinatra 3.0.6
サンプルコード
- vim app.rb
# frozen_string_literal: true
require 'sinatra'
# / を管理するクラス
class MyApp < Sinatra::Base
def initialize(path)
super()
@path = path
routing
end
def routing
MyApp.get @path do
'hello'
end
end
# 例えばルーティングに関する情報を使って何かを生成することもできる
def to_h
{
path: @path
}
end
end
config.ru
-
vim config.ru
# frozen_string_literal: true
require 'rack'
require './app'
run Rack::URLMap.new(
{
'/home' => MyApp.new('/') # ここを /fuga などにすると /home/fuga にアクセスできる
}
)
動作確認
-
bundle exec rackup config.ru
ツールとして使う
Web アプリとしてではなくルーティング内に定義したインスタンスメソッドを別のツールとして使うこともできます
- vim export.rb
# frozen_string_literal: true
require './app'
app = MyApp.new!('/')
puts app.to_h
ポイントは new!
を使って強制的にインスタンス化して使います
rackup を挟んでいないので通常のクラスとして使えます
メリット
ルーティングをクラスとして定義することで複数のルーティングを定義した場合に共通の処理を親クラスに抽象化することができます
Mix-in なども使えます (そもそも Sinatra にはミドルウェアという機能があるのでそれと同じように使える)
逆に同じようなページを生成するのであればすでにあるルーティング用のクラスを使って同じページを生成できます
またルーティングに必要な情報 (パスやリクエストパラメータ、テンプレートに与える情報、ヘッダ、認証情報) などをクラス内で管理することができるようになるのでコードの可読性も上がります
デメリット
ルーティングを追加するのにわざわざクラスを一つ追加する必要があります
またせっかく DSL で簡単にアプリを定義できるのにクラス化するためのコードを増えるので記述量は多くなります
Rails っぽくなってしまうというのもあるかなと思います
最後に
使用するかどうかは開発するプロダクトの規模の大きさにもよるかもしれません
これにデータベースが絡んで来る場合などはむしろ Sinatra ではなく Rails を使ったほうがいいまであります
0 件のコメント:
コメントを投稿