💎
RubyのアプリケーションをVercelで動かす
概要
VercelでRubyのランタイムもサポートされているそうなのでSinatraで作成したTodoリストアプリを動かしてみました。
実際のコードは下記になります。
前提(VercelのRuby Runtime)
VercelのRuby Runtimeの説明をみると下記のようにリクエストを受け取ってレスポンスを返すとのことでした。
ので、このリクエストをSinatraのアプリケーションに渡すことで動かすようにします。
api/index.rb
require 'cowsay'
Handler = Proc.new do |request, response|
name = request.query['name'] || 'World'
response.status = 200
response['Content-Type'] = 'text/text; charset=utf-8'
response.body = Cowsay.say("Hello #{name}", 'cow')
end
Sinatraアプリケーションへリクエストを渡す
Sinatraは、Ruby on Railsと同様にRackを基盤に動いているので、受け取ったrequestをrackのインターフェースに合わせてSinatraのアプリケーションに渡してあげます。
require_relative '../app/main'
Handler = Proc.new do |request, response|
app = MyApp.new
env = {
'REQUEST_METHOD' => request.request_method,
'PATH_INFO' => request.path,
'QUERY_STRING' => request.query_string,
'rack.input' => StringIO.new(request.body || "")
}
status, headers, body = app.call(env)
response.status = status
headers.each { |key, value| response[key] = value }
response.body = body.join
end
↑では簡易的に必要そうなものだけ詰めましたが、Rackのenvに関しての詳細は下記のSpecドキュメントで確認いただけます。
Sinatraのcallメソッド
参考にさせて頂いた記事
/
ベースのエンドポイントにする
verce.jsonで/
をベースにしたエンドポイントを構築します。
{
"version": 2,
"builds": [
{ "src": "api/index.rb", "use": "@vercel/ruby" }
],
"routes": [
{ "src": "/(.*)", "dest": "/api/index.rb" }
]
}
アプリケーション層での処理
ここまでできれば普通のSinatraアプリと変わらないのでドキュメントを参考にGET/POSTのエンドポイントをそれぞれ実装してみました。
app/main.rb
require 'sinatra/base'
require 'dotenv/load'
require_relative './models/todo'
class MyApp < Sinatra::Base
get '/' do
todos = Todo.all
erb :template, locals: { todos: todos }
end
post '/add_todo' do
text = params['text']
Todo.create(text)
erb :success
end
end
その他
次はRailsのアプリケーションを動かしてみたいです。
Discussion