🎉

Rilas7.1.3 Grapeとgrape-entityを使ってサクッとAPIを作成

2024/02/29に公開

はじめに

Grapeは、RubyでRESTful APIを簡単に作成するためのフレームワークです。
この記事では、「Grape」と「grape-entity」を使ってAPIを簡単に作成する方法をサクッとご紹介します。

※Grape導入のため、モデルの作成、データの作成、テスト部分は省略します。以下の記事でモデルの作成、データの作成、テストの導入部分を記述しています。参考程度に読んでみて下さい。

実行環境

  • M2 mac mini
  • Rails 7.1.3
  • Ruby 3.2.3
  • Mysql 8.0
  • Docker 25.0.2
  • vscodeエディタ

環境構築が済んでいない方はこちらを参考に環境構築を行なってください。
https://zenn.dev/kei1232/articles/0fac51829570c1

Schemafileの導入がまだの方はこちらから設定してください。
https://zenn.dev/kei1232/articles/5c31cc58453453

RSpecの導入 ※こちらは導入しなくてもOKです。
https://zenn.dev/kei1232/articles/941b465240bc1d

Grape、corsをgemファイルに追加

Gemfile
# cors設定
gem 'rack-cors', '~> 2.0', '>= 2.0.1'

# Web APIフレームワーク
gem 'grape', '~> 2.0'
gem 'grape-entity', '~> 1.0'

追加したGemをインストール

docker-compose exec web bundle install

CORSの設定

※ここの設定がなくてもAPIは動くと思います。また設定が間違っている可能性があります。

config/application.rb
    # Cors設定
    config.middleware.use Rack::Cors do
      allow do
        origins "*"
        resource "*", headers: :any, methods: [:get, :post, :put, :delete, :options]
      end
    end
config.ru
require_relative "config/environment"
require 'rack/cors'

use Rack::Cors do
  allow do
    origins '*'
    resource '*', headers: :any, methods: [:get, :post, :put, :delete, :options]
  end
end

run Rails.application
Rails.application.load_server

フォルダ&ファイルの作成

mkdir app/api &&  mkdir app/api/v1
touch app/api/root.rb && touch app/api/v1/{root.rb,tasks.rb} 

config/initializers/inflections.rbの編集

apiフォルダがApiと認識されるため、APIとなるようにする。

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

APIの作成

app/api/v1/tasks.rb
  module V1
    class Tasks < Grape::API
      resource :tasks do
        desc 'タスクの一覧取得'
        get '' do
          tasks = Task.all
          present tasks
        end
      end
    end
  end

app/api/tasks.rbをapi/v1/root.rbのRootに紐づける

  module V1
    class Root < Grape::API
      version 'v1', using: :path
      format :json
      content_type :json, 'application/json;charset=UTF-8'
      mount V1::Tasks
    end
  end

app/api/root.rbにv1で作成したRootを紐づける

app/api/root.rb
  class Root < Grape::API
    prefix 'api'

    # api/v1/root.rbをマウント
    mount V1::Root
  end

config/routes.rbに作成したAPIのroutesを追加

config/routes.rb
Rails.application.routes.draw do
  # api/root.rbをマウント
  mount Root => '/'
end

ルート確認

※通常rails routesコマンドのルートの確認を行いますが、grapeの場合作成したAPIのroutesは出力されません。

そのためrakeファイルを作成し、作成したAPIのルートを出力するコードを記載します。

rakeファイルの作成

touch lib/tasks/grape.rake

lib/tasks/grape.rakeの編集

以下、作成したAPIを出力するコードになります。

ib/tasks/grape.rake
namespace :grape do
  task :routes => :environment do
    Grape::API.subclasses.each do |subclass|
      subclass.routes.each do |e|
        puts "%-10s %-6s %-24s %s" % [subclass, e.request_method, e.path, e.description]
      end
      puts
    end
  end
end

routesの確認

docker-compose exec web bundle exec rake grape:routes

http://localhost:3001/api/v1/tasks

※設定しているポート番号でAPIを叩いてくだい。またレスポンスがエラーになる場合はコードが間違っているか、またはDockerが動作しているか確認してください。

PostmanでAPIを確認

※ブラウザ上で上記のURLにアクセスしても確認できます。
データを取得できたことが確認できました。

次に「grape-entity」を使用して取得したデータを整形し、欲しいデータを取得できるようにします。

フォルダとファイルの作成

mkdir app/api/entitys
touch app/api/entitys/task.rb

app/api/entitys/task.rbの編集

今回はidtitlecontentis_completedを返すEntityを作成します。

task.rb
  module Entitys
    class Task < Grape::Entity
      expose :id, documentation: { type: 'Integer' } # id
      expose :title, documentation: { type: 'String' } # タスクのタイトル
      expose :content, documentation: { type: 'String' } # タスクの内容
      expose :is_completed, documentation: { type: 'boolean' } # 完了、未完了フラグ
      # expose :created_at, documentation: { type: 'DateTime' } # 作成日時
      # expose :updated_at, documentation: { type: 'DateTime' } # 更新日時
    end
  end

app/api/v1/tasks.rbの修正

タスクの一覧取得タスクの詳細取得タスクの作成タスクの更新タスクの削除を追加&修正を行います。

task.rb
  module V1
    class Tasks < Grape::API
      resource :tasks do
        desc 'タスクの一覧取得', { success: { model: Entitys::Task }, is_array: true }

        get '' do
          tasks = Task.all
          present tasks, with: Entitys::Task
        end

        desc 'タスクの詳細取得',{ success: { model: Entitys::Task } }
        params do # パラメータの定義
          requires :id, type: Integer, description: 'ID'
        end
        get '/:id' do
          task = Task.find(params[:id])
          present task, with: Entitys::Task
        end

        desc 'タスクの作成',{ success: { model: Entitys::Task } }
        params do # パラメータの定義
          requires :title, type: String, description: 'タスクのタイトル'
          requires :content, type: String, description: 'タスクの内容'
        end
        post '' do
          task = Task.create(title: params[:title], content: params[:content])
          present task, with: Entitys::Task
        end

        desc 'タスクの更新',{ success: { model: Entitys::Task } }
        params do # パラメータの定義
          requires :id, type: Integer, description: 'ID'
          optional :title, type: String, description: 'タスクのタイトル'
          optional :content, type: String, description: 'タスクの内容'
          optional :is_completed, type: Boolean, description: '完了、未完了フラグ'
        end
        put '/:id' do
          task = Task.find(params[:id])
          task.title = params[:title] if params[:title]
          task.content = params[:content] if params[:content]
          task.is_completed = params[:is_completed] if params[:is_completed]
          task.updated_at = DateTime.now
          task.save
          present task, with: Entitys::Task
        end

        desc 'タスクの削除',{ success: { model: Entitys::Task } }
        params do # パラメータの定義
          requires :id, type: Integer, description: 'ID'
        end
        delete '/:id' do
          task = Task.find(params[:id])
          task.destroy
          present task, with: Entitys::Task
        end
      end
    end
  end

API確認

http://localhost:3001/api/v1/tasks

※設定しているポート番号でAPIを叩いてくだい。またレスポンスがエラーになる場合はコードが間違っているか、またはDockerが動作しているか確認してください。

最後にルートの確認

docker-compose exec web bundle exec rake grape:routes

まとめ

Grapeとgrape-entityを活用すれば、RESTful APIを簡単に、効率的に開発できます。ぜひ本記事を参考に、API開発に挑戦してみてください。

Discussion