---
title: "Grape API入門：RubyのGrape gem 4.0でREST APIを作る手順とRails連携"
url: "https://www.issoh.co.jp/tech/details/3855/"
published: 2024-10-16
updated: 2026-10-28
categories: ["Ruby"]
publisher: "株式会社一創"
---

# Grape API入門：RubyのGrape gem 4.0でREST APIを作る手順とRails連携

Grapeは、RubyでREST風のJSON APIを作るためのフレームワークです。Rackアプリとして単体で動かすことも、Railsの `routes.rb` に `mount` して既存アプリのAPI層にすることもできます。この記事では、2026年9月に出たGrape 4.0.1を使い、インストールからRailsへのマウント、パラメータ検証、grape-entityによるレスポンス整形、バージョニング、エラー処理、RSpecでのテスト、grape-swaggerによるドキュメント出力までを、Ruby 4.0.6・Rails 8.1.4で実行したコードで説明します。3系以前から上げる人向けに、4.0で挙動が変わった箇所も実行結果つきでまとめました。

## まとめ：Grape 4.0でREST APIを作るときの要点

- **最新版と要件**：Grapeの最新は4.0.1（2026-09-15公開）です。Ruby 3.3以上とactivesupport 7.2以上が必要です。
- **Railsへの組み込み**：`app/api` にクラスを置いて `routes.rb` で `mount` します。モジュール名を `API` にするなら、Zeitwerk向けに `inflect.acronym "API"` の設定が必須です。設定しないと `NameError` で起動しません。
- **Grapeを選ぶ場面**：返すものがJSONだけで、宣言的なパラメータ検証と複数バージョンの並走が要るAPIです。RailsでHTML画面やフォームも提供する予定なら、通常のRailsアプリを選ぶほうが追加設定を減らせます。
- **4.0での注意**：`rescue_from` でHashを返す書き方は500になります。ルートより下に書いた `use`・`helpers`・`rescue_from` はそのルートに効きません。上げる前に該当箇所を探して直してください。

以下、Grapeの位置付けと使い分けから順に説明します。

## Grapeとは：Ruby製REST APIフレームワークの位置付け

公式READMEはGrapeを「a REST-like API framework for Ruby」と説明しています（[ruby-grape/grape README v4.0.1](https://github.com/ruby-grape/grape/blob/v4.0.1/README.md)）。RackやRails、Sinatraの上で動き、エンドポイントの定義、入力の検証と型変換、出力形式の切り替え、バージョニングをDSLで書けます。ビュー、ORM、アセットは持ちません。DBアクセスはRailsのActive Recordなど、外側の仕組みをそのまま使います。

### 最新版4.0.1と動作要件

RubyGemsに最初の版が登録されたのは2010年8月で、累計ダウンロードは8,700万回を超えます（[RubyGems.org grape](https://rubygems.org/gems/grape)、2026-10-28時点）。メジャー版は2025年11月の3.0.0から1年足らずで4.0.0に進みました。

| 版     | 公開日        | 必要なRuby | 主な変化                     |
| ----- | ---------- | ------- | ------------------------ |
| 4.0.1 | 2026-09-15 | 3.3以上   | ネストしたmountの再マウント不具合を修正   |
| 4.0.0 | 2026-09-07 | 3.3以上   | 3.2・3.3で予告した非推奨を削除       |
| 3.3.0 | 2026-06-20 | 3.3以上   | Ruby 3.2を切り捨て            |
| 3.0.0 | 2025-11-15 | 3.0以上   | Ruby 2.7を切り捨て・Rack 3.2対応 |

4.0.1の実行時依存は activesupport 7.2以上、rack 2.2.4以上、mustermann 4.0以上、dry-types、dry-configurable、zeitwerkです。Rails 7.1以前のアプリはactivesupportの条件を満たさないので、Rails側を先に上げる必要があります。GitHubのCIは Ruby 3.3・3.4・4.0 で回っています。手元のRubyが古い場合は、[Rubyの最新バージョンと各系列のサポート期限](/tech/details/10592/)で上げ先を決めてください。

### Rails APIモード・Sinatraとの使い分け

Grapeが向くのは、返すものがJSONに限られ、パラメータの型と値域をエンドポイントの直前に宣言したい、v1とv2を並べて長く運用したい、という条件がそろうAPIです。`version` と `params` のDSLが、まさにこの2つのためにあります。

管理画面やフォームをRails自身で描画する予定なら、`--api` を付けない通常のRailsアプリで始めてください。別のフロントエンドへJSONだけを提供する構成なら、APIモードも選択肢です。通常のRailsアプリならビューやブラウザ向け機能を利用できます。APIモードからRailsで描画する画面を追加する場合は、コントローラの継承元やセッションなどの設定を見直す必要があります。手順は[Rails APIモードでの作成手順とJWT認証](/tech/details/2905/)にまとめています。Sinatraは自由度が高い一方、入力検証もバージョニングも自前で書くことになります。チームで同じ規約のAPIを量産するなら、Grapeの決まった書き方のほうが揃えやすいです。

## Grapeのインストールとconfig.ruでの単体起動

Railsを使わない場合は、Gemfileに `grape` とRackサーバーを入れて、`config.ru` にAPIクラスを書けば動きます。

```
# Gemfile
source "https://rubygems.org"

gem "grape", "~> 4.0"
gem "puma"
gem "rackup"
```

```
# config.ru
require "grape"

class PingAPI < Grape::API
  format :json

  get :ping do
    { message: "pong", grape: Grape::VERSION }
  end
end

run PingAPI
```

`bundle install` のあと `bundle exec rackup -p 9393` で起動し、`curl localhost:9393/ping` を送ると `{"message":"pong","grape":"4.0.1"}` が返ります。`format :json` により、ブロックの戻り値のHashがJSONになり、`content-type: application/json` が付きます。定義していないパスへのリクエストは404と `x-cascade: pass` ヘッダーで返り、Railsなど外側のRackアプリに処理を譲れるようになっています。GrapeがRackの上でどう呼ばれるかは[Rackの仕様とミドルウェアの書き方](/tech/details/5598/)で、Gemfileの書き方は[gemとBundlerの使い方](/tech/details/4221/)で説明しています。

## RailsアプリにGrapeをマウントする手順

Railsでは、Grapeのクラスを `app/api` 配下に置き、`config/routes.rb` で `mount` します。ここではRails 8.1.4の `rails new --api` で作ったアプリに、ステータス投稿のAPIを載せます。モデルは `bin/rails g model Status text:string visibility:string` で生成し、`bin/rails db:migrate` でテーブルも作成済みとします。

### app/apiの配置とroutes.rbのmount

```
# Gemfile（追記）
gem "grape", "~> 4.0"
gem "grape-entity", "~> 1.1"
```

```
app/api/api/base.rb                 # API::Base（入口）
app/api/api/v1/base.rb              # API::V1::Base（v1の共通設定）
app/api/api/v1/statuses.rb          # API::V1::Statuses（エンドポイント）
app/api/api/v1/entities/status.rb   # API::V1::Entities::Status（出力形式）
```

```
# app/api/api/base.rb
module API
  class Base < Grape::API
    prefix :api
    format :json

    mount API::V1::Base
  end
end
```

```
# config/routes.rb
Rails.application.routes.draw do
  mount API::Base => "/"
end
```

`app` 直下のディレクトリはRailsの自動読み込みの起点になるので、`app/api/api/base.rb` は `API::Base` として読まれます。`api` が2段になるのはこのためです。リソースごとにクラスを分け、`mount` で束ねると、URLの階層とファイルの配置が一致します。

### Zeitwerkの「API」acronym設定

RailsのZeitwerkは、ファイル名 `api` を既定で `Api` と解釈します。このままでは `API` モジュールが見つからず、`bin/rails zeitwerk:check` は次のエラーで止まります。

```
NameError: uninitialized constant API::V1 (NameError)

    mount API::V1::Base
             ^^^^
```

READMEが指示するとおり、`config/initializers/inflections.rb` に頭字語として登録すると解決します。

```
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym "API"
end
```

設定後に `bin/rails zeitwerk:check` を実行すると `All is good!` が出ます。2016年ごろの記事にある `config.paths.add` や `autoload_paths` を足す手順は、Zeitwerkが標準になった今のRailsでは不要です。この設定はアプリ全体に効くので、既存の `app/models/api_client.rb` は `ApiClient` ではなく `APIClient` を定義していると見なされます。既存クラスに `Api` で始まる名前があるなら、モジュール名を `Api` にしてacronymを設定しない選択もあります。

## エンドポイントとパラメータ検証の書き方

v1の共通設定とエンドポイントを書きます。`version`、`rescue_from`、`mount` は、それを効かせたいルートより上に書いてください（4.0で厳密になった点で、後述します）。

```
# app/api/api/v1/base.rb
module API
  module V1
    class Base < Grape::API
      version "v1", using: :path

      rescue_from ActiveRecord::RecordNotFound do |e|
        error!({ error: "not_found", detail: e.message }, 404)
      end

      rescue_from Grape::Exceptions::ValidationErrors do |e|
        error!({ error: "invalid_params", detail: e.full_messages }, 400)
      end

      mount API::V1::Statuses
    end
  end
end
```

```
# app/api/api/v1/statuses.rb
module API
  module V1
    class Statuses < Grape::API
      resource :statuses do
        desc "ステータスの一覧を返す"
        params do
          optional :limit, type: Integer, default: 20, values: 1..100
        end
        get do
          statuses = ::Status.order(id: :desc).limit(params[:limit])
          present statuses, with: Entities::Status
        end

        desc "ステータスを1件作成する"
        params do
          requires :text, type: String, allow_blank: false, length: { max: 140 }
          optional :visibility, type: String, values: %w[public private], default: "public"
        end
        post do
          status = ::Status.create!(declared(params))
          present status, with: Entities::Status
        end

        route_param :id, type: Integer do
          desc "ステータスを1件返す"
          get do
            present ::Status.find(params[:id]), with: Entities::Status
          end

          desc "ステータスを削除する"
          delete do
            ::Status.find(params[:id]).destroy!
            body false
          end
        end
      end
    end
  end
end
```

### resourceとroute\_paramによるURL設計

`resource :statuses` がURLの階層を、`route_param :id` がパスの変数を作ります。`prefix :api` と `version "v1", using: :path` と合わせて、`API::Base.routes` は次の4本になります。

```
GET    /api/:version/statuses(.json)
POST   /api/:version/statuses(.json)
GET    /api/:version/statuses/:id(.json)
DELETE /api/:version/statuses/:id(.json)
```

`route_param :id, type: Integer` と型を付けると、`/api/v1/statuses/abc` のような数字でないIDはGrapeのルートに一致しません。リクエストはRails側に渡り、ほかのルートにも一致しなければ404になります。レスポンス形式はAcceptヘッダーやRailsの設定に依存します。JSONで400を返したいなら、型を外して `params do requires :id, type: Integer end` で検証してください。`.json` 拡張子付きのURLも同じエンドポイントに届きます。

### paramsとdeclaredによる入力の検証

`params do ... end` に書いた条件を満たさないリクエストは、エンドポイントの本体に入る前に止まります。上のコードに対する実際のレスポンスは次のとおりです。

| リクエスト                             | ステータス | レスポンスの要点                          |
| --------------------------------- | ----- | --------------------------------- |
| POST `{"text":"hello"}`           | 201   | visibilityは既定値public              |
| POST `{"text":""}`                | 400   | text is empty                     |
| POST textが141文字                   | 400   | length less than or equal to 140  |
| POST visibilityがfriends           | 400   | does not have a valid value       |
| GET `?limit=0`                    | 400   | limit does not have a valid value |
| GET `/statuses/999`               | 404   | not\_found（rescue\_from）          |
| DELETE `/statuses/1`（id=1が存在する場合） | 204   | 本文なし                              |

POSTの既定ステータスは201、`body false` を返すと204です。`declared(params)` は `params` ブロックで宣言したキーだけを取り出すので、`{"text":"x","admin":true}` を送っても `admin` は `create!` に渡りません。Railsのコントローラでいう Strong Parameters の役割を、宣言そのものが兼ねています。`rescue_from Grape::Exceptions::ValidationErrors` を書かなかった場合、エラーは `{"error":"text is missing"}` のように、メッセージ1本の形で返ります。

## grape-entityによるレスポンス整形

モデルをそのまま返すと、DBの列がすべてJSONに出ます。[grape-entity](https://github.com/ruby-grape/grape-entity)（最新1.1.0、2026-06-04）のEntityクラスで、公開する項目と名前を決めます。

```
# app/api/api/v1/entities/status.rb
module API
  module V1
    module Entities
      class Status < Grape::Entity
        format_with(:iso8601) { |t| t.iso8601 }

        expose :id
        expose :text
        expose :visibility
        expose :created_at, as: :posted_at, format_with: :iso8601
      end
    end
  end
end
```

エンドポイントでは `present モデル, with: Entities::Status` と書きます。出力は `{"id":1,"text":"hello","visibility":"public","posted_at":"2026-10-28T07:52:50Z"}` で、`updated_at` は出ません。`as:` で列名と違うキー名を付けられるので、DBの列名を変えてもAPIの契約は変わりません。Entityなしでも、ブロックからHashを返せばJSONになります。項目数にかかわらず、公開項目を明示した単純な応答ならHashで足ります。複数のエンドポイントで出力定義を共有するならEntityを使うと重複を減らせます。

## APIのバージョニングと複数バージョンの並走

`version` の指定方法は `:path`（既定）、`:header`、`:accept_version_header`、`:param` の4つです。

| using:                   | クライアントの指定方法        | 例                               |
| ------------------------ | ------------------ | ------------------------------- |
| :path                    | URLに版を含める          | /api/v1/statuses                |
| :header                  | Acceptのベンダー型       | application/vnd.example-v1+json |
| :accept\_version\_header | Accept-Versionヘッダー | Accept-Version: v1              |
| :param                   | クエリ文字列             | ?apiver=v1                      |

迷ったら `:path` を選んでください。ログやブラウザで版がそのまま見え、CDNのキャッシュキーも分かれます。`:header` と `:accept_version_header` は、ヘッダーが無いリクエストを最初に一致した版で処理します。`strict: true` を付けるとヘッダー無しのリクエストを受け付けなくなり、既定では404、`cascade: false` も付けると406が返ります。

v2を足すときは、変えたいエンドポイントだけをv2に書き、v1に `version "v1", "v2"` と並べると、変えていないエンドポイントをv2でも共有できます。このとき、新しい版を先に `mount` する必要があります。

```
class V1 < Grape::API
  version "v1", "v2", using: :path
  format :json
  get(:statuses) { { from: "v1" } }
  get(:legacy) { { from: "v1" } }
end

class V2 < Grape::API
  version "v2", using: :path
  format :json
  get(:statuses) { { from: "v2" } }
end

class Root < Grape::API
  mount V2   # 新しい版を先に
  mount V1
end
```

この順なら `/v2/statuses` はv2の実装を、`/v2/legacy` はv1の実装を返します。`mount V1` を先に書くと、`/v2/statuses` もv1の実装が返ります。エラーにはならないので、v2を足したのに挙動が変わらないときは、まずmountの順を確かめてください。

## rescue\_fromによるエラー応答の統一

例外は `rescue_from` で受け、`error!(本文, ステータス)` で返します。前述の `API::V1::Base` のように、例外クラスごとにステータスと本文の形を決めておくと、クライアントは `error` キーだけを見て分岐できます。`rescue_from :all` が包括的に捕捉するのは `StandardError` とそのサブクラスです。本番では内部のメッセージがそのまま外に出ないよう、本文を固定文言にしてログ側に詳細を残してください。

バリデーションエラーだけGrape既定の400のまま返したいときは、`rescue_from :grape_exceptions` を併記します。4.0からは、`rescue_from StandardError` のようにクラスで書いた包括ハンドラより `:grape_exceptions` が優先されるようになりました（[UPGRADING.md](https://github.com/ruby-grape/grape/blob/v4.0.1/UPGRADING.md)）。3系では、この組み合わせでもバリデーションエラーが包括ハンドラ側の応答（500など）になっていました。

## RSpecのrequest specによるGrape APIのテスト

Railsにマウントしているなら、rspec-railsのrequest specでURLを叩くのがいちばん手軽です。ルーティング、Grapeの検証、`rescue_from`、Entityの出力をまとめて確かめられます。

```
# Gemfile（test グループ）
group :test do
  gem "rspec-rails"
end
```

```
# spec/requests/api/v1/statuses_spec.rb
require "rails_helper"

RSpec.describe "API::V1::Statuses", type: :request do
  describe "POST /api/v1/statuses" do
    it "作成したステータスを201で返す" do
      post "/api/v1/statuses", params: { text: "hello" }

      expect(response).to have_http_status(201)
      expect(response.parsed_body).to include("text" => "hello", "visibility" => "public")
    end

    it "textが空なら400とエラー内容を返す" do
      post "/api/v1/statuses", params: { text: "" }

      expect(response).to have_http_status(400)
      expect(response.parsed_body["error"]).to eq("invalid_params")
    end
  end

  describe "GET /api/v1/statuses/:id" do
    it "存在しないidなら404を返す" do
      get "/api/v1/statuses/999"

      expect(response).to have_http_status(404)
      expect(response.parsed_body["error"]).to eq("not_found")
    end
  end
end
```

Gemfileへの追記後に `bundle install` を実行し、`bin/rails g rspec:install` で設定ファイルを生成したあと `bundle exec rspec` を実行すると `3 examples, 0 failures` になります。request specの書き方は[Rails 8・RSpec 8でのrequest specの書き方](/tech/details/3993/)で詳しく扱っています。Railsを使わない単体のGrapeなら、`rack-test` を入れて `include Rack::Test::Methods` し、`def app = PingAPI` を定義すれば同じように `get "/ping"` と書けます。

テストで `Grape::Endpoint.before_each` を使ってヘルパーを差し替えている場合、4.0からは `spec_helper.rb` に `require "grape/testing"` が必要です。3系では書かなくても読み込まれていましたが、4.0では `NoMethodError` になります。

## grape-swaggerによるAPIドキュメントの出力

[grape-swagger](https://github.com/ruby-grape/grape-swagger)（最新2.2.0）は、`desc` と `params` の宣言からAPI仕様書のJSONを作ります。2.2.0はgrape 2.1以上5.0未満に対応しているので、4.0.1とそのまま組み合わせられます。

```
# Gemfile（追記）
gem "grape-swagger", "~> 2.2"
gem "grape-swagger-entity", "~> 0.7"

# app/api/api/base.rb の mount の下に追記
add_swagger_documentation(
  info: { title: "Status API" }
)
```

`GET /api/swagger_doc` で仕様書が返り、`paths` に `/api/v1/statuses` と `/api/v1/statuses/{id}` が並びます。出力の形式は `"swagger": "2.0"`、つまりOpenAPI 2.0です。OpenAPI 3系を前提にしたツールへ渡すなら、変換をはさんでください。表示するSwagger UIの立て方は[Swagger Editor・UIをDockerで動かす手順](/tech/details/17451/)を参照してください。

## Grape 4.0へ上げるときの破壊的変更と移行手順

4.0.0は、3.2と3.3で非推奨にした書き方を削除した版です。CHANGELOGの大半は内部構造の整理ですが、アプリのコードに影響するものもあります。Grape 4.0.1で実行して挙動を確かめたものを中心に並べます。

| 変更                           | 3系までの挙動     | 4.0の挙動                      |
| ---------------------------- | ----------- | --------------------------- |
| rescue\_fromでHashを返す         | エラー応答として解釈  | 500 Invalid response        |
| ルートより下のrescue\_from・use      | 条件次第で効く     | そのルートには効かない                 |
| :grape\_exceptionsと包括ハンドラ    | 包括ハンドラが優先   | Grapeの例外は本来の400等            |
| Grape::Endpoint.before\_each | 自動で読み込み     | require “grape/testing” が必要 |
| http\_digest                 | 最初のリクエストで例外 | クラス定義時にNoMethodError        |
| descの default キー             | そのまま使えた     | default\_response へ改名（非推奨化） |
| 自作error\_formatterのbacktrace | 常に中身あり      | backtrace: true 以外は空配列      |

### 4.0のエラー処理・登録順の変更とreturnの非推奨

1つ目は `rescue_from` の戻り値です。3系で動いていた次の書き方は、4.0では503ではなく `500 {"error":"Invalid response"}` を返します。`error!` に書き換えると、意図どおり503になります。

```
# 4.0では500になる
rescue_from :all do |e|
  { message: e.message, status: 503, headers: {} }
end

# 4.0での書き方
rescue_from :all do |e|
  error!({ error: e.message }, 503)
end
```

2つ目は登録の位置です。`get` の下に `rescue_from ArgumentError` を書いたAPIでは、例外がハンドラに捕まらずにそのまま外へ出ました。3系でこの配置が動いていたのは、同じ種類の登録が先に1つあった場合だけです。`use`、`helpers`、`before` も同じ扱いなので、すべてルートより上へ移してください。

3つ目はエンドポイント内の `return` です。3.0から非推奨で、`next` に置き換えます。4.0.1ではまだ値を返しますが、削除予告が出ている書き方なので、上げるついでに直しておくと次の版で困りません。

新機能では、HTTPの [QUERYメソッド（RFC 10008）](https://www.rfc-editor.org/info/rfc10008/)に対応しました。`query "/search" do ... end` と書くと、検索条件をリクエスト本文のJSONで受け取れます。GETのクエリ文字列に入りきらない複雑な検索条件を、安全で冪等なメソッドとして扱えます。

### 3系から上げる前の確認手順

Rubyを3.3以上、activesupportを7.2以上にしてから、次の文字列をリポジトリで検索します。`rescue_from` のブロック末尾のHash、`http_digest`、`before_each`、`desc` の `default:`、エンドポイント内の `return` です。加えて、各APIクラスでルート定義の後ろに `use`、`helpers`、`rescue_from` が書かれていないかを目で確認してください。ここは文字列検索では見つけにくく、しかも4.0ではエラーにならずに黙って効かなくなります。修正後にrequest specを流し、エラー時のステータスが変わっていないかを確かめます。変更の全体は[CHANGELOG.md](https://github.com/ruby-grape/grape/blob/v4.0.1/CHANGELOG.md)とUPGRADING.mdの「Upgrading to >= 4.0.0」にあります。

Grapeで作ったAPIの改修や、既存システムとのAPI連携の設計を外部に頼みたい場合は、[API開発・システム連携の支援](/service/system/api/)でも相談を受け付けています。認証をRackミドルウェアとして足す方法は、[Wardenのカスタム戦略とJWT認証](/tech/details/7166/)が参考になります。

## よくある質問

### Grape gemとは何ですか？

RubyでREST風のJSON APIを作るためのフレームワークです。Rackアプリとして単体で動かすことも、Railsにmountして使うこともできます。エンドポイント、パラメータ検証、バージョニングをDSLで宣言できる一方、画面やORMは持ちません。

### Grapeの最新バージョンと対応するRubyは？

2026年10月時点の最新は4.0.1（2026-09-15公開）で、Ruby 3.3以上とactivesupport 7.2以上が必要です。版の更新が速いので、導入時はRubyGems.orgのgrapeのページで最新を確認してください。

### GrapeとRailsのAPIモードはどちらを使うべきですか？

JSONだけを返し、複数バージョンを並走させるAPIならGrapeが向きます。Rails自身で画面やフォームも提供する予定なら通常のRailsアプリを、別のフロントエンドへJSONだけを提供するならAPIモードを検討してください。

### RailsにmountしたGrapeが「uninitialized constant API」で動かないのはなぜですか？

Zeitwerkが `api` を `Api` と解釈しているためです。`config/initializers/inflections.rb` に `inflect.acronym "API"` を追加すると解決します。`bin/rails zeitwerk:check` で確認できます。

### grape-entityは必須ですか？

必須ではありません。Hashを返せばJSONになります。ただ、モデルをそのまま返すと全列が出るため、公開項目を管理したいAPIではEntityを使うほうが安全です。grape-swagger-entityを入れて `desc` の `success:` にEntityを渡すと、その項目定義が仕様書にも載ります。

## 関連記事

- [Rails APIとは？作成手順・JWT認証・React連携・Docker環境を実装解説【Rails 8.1】](/tech/details/2905/)
- [Rackとは？Rubyのサーバーとアプリをつなぐ仕様とミドルウェアの書き方【Rack 3.2】](/tech/details/5598/)
- [request specとは？Rails 8・RSpec 8でのリクエストスペックの書き方](/tech/details/3993/)
- [Swaggerとは：Editor・UIをDockerで動かす手順とOpenAPI 3.2対応の現況](/tech/details/17451/)
- [Wardenのカスタム戦略の作り方：valid?・authenticate!とDevise連携・JWT認証](/tech/details/7166/)

---

出典: [Grape API入門：RubyのGrape gem 4.0でREST APIを作る手順とRails連携](<https://www.issoh.co.jp/tech/details/3855/>)（株式会社一創）
