💎

RubyのアプリケーションをVercelで動かす

2024/11/10に公開

概要

VercelでRubyのランタイムもサポートされているそうなのでSinatraで作成したTodoリストアプリを動かしてみました。

実際のコードは下記になります。

https://github.com/K-Sato1995/vercel-ruby-runtime

前提(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ドキュメントで確認いただけます。

https://github.com/rack/rack/blob/main/SPEC.rdoc#label-The+Environment

Sinatraのcallメソッド

https://github.com/sinatra/sinatra/blob/7a5c499f0e6099137fd1cb4ee20178af2a125d47/lib/sinatra/base.rb#L1501-L1503

参考にさせて頂いた記事

https://qiita.com/junjis0203/items/8dfd506d0f66455e589e

/ベースのエンドポイントにする

verce.json/をベースにしたエンドポイントを構築します。

{
    "version": 2,
    "builds": [
      { "src": "api/index.rb", "use": "@vercel/ruby" }
    ],
    "routes": [
      { "src": "/(.*)", "dest": "/api/index.rb" }
    ]
  }

アプリケーション層での処理

ここまでできれば普通のSinatraアプリと変わらないのでドキュメントを参考にGET/POSTのエンドポイントをそれぞれ実装してみました。

https://sinatrarb.com/intro.html

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