⛏️

RailsによるAPI開発のTips

2022/06/01に公開

はじめに

はじめまして。
東大院卒エンジニアの遠藤和真です。
この記事では,Pythonばかりいじっていた僕がRailsでAPI開発をする際にやって便利だったTipsを紹介していきます。

もっとこうしたほうがいいといった情報がありましたら気軽にコメントいただけると大変嬉しいです。

制作する物

今回は簡単なTodoアプリを作ることを想定し,ポイントとなる部分をピックアップしていきます。
今回紹介した手順だけでアプリが完成するわけではないことをご了承ください。

dbはMysqlを使います。
モデルはUserとTaskの2つです。

Docker compose

環境構築にはDocker composeを使います。apiのコンテナとdbのコンテナをそれぞれ簡単に動かすことができます。さらにローカルでのサーバの起動も以下のように行うことができます。

docker-compose.yml
# 省略
services:
    api:
	# 省略
        command: bundle exec rails s -p 3000 -b '0.0.0.0'
# 省略

rails new your_app_name --api

Rails newにオプション--apiをつけることでAPIモードでアプリを作成できます。

docker-compose run api rails new todo_app_api -d mysql --api

Gemのインストール

早めに必要なGemをインストールしておくと,generateやmigration時に処理をしてくれるためにお得な場合があります。

デフォルトでインストールされないGemでおすすめは

  • pry-rails:デバッグツール
  • rspec-rails:TDDテストツール
  • factory_bot_rails:テストデータの作成ツール
  • faker:ランダムなテストデータの作成ツール。factory_botと一緒に使うと便利
  • shoulda-matchers:テーブル間のアソシエーションのテストを簡易的に書ける
  • annotate:テーブルのカラムの情報をコメントに書き出してくれる

詳しい使い方はそれぞれのREADME.mdを参照してください。インストールコマンドを実行するものは早めに実行しておきましょう。

scaffold

scaffoldをすることで簡単にコントローラやモデルやビュー(今回の場合はjbuilder)やマイグレーションファイルを作成できます。
foreign keyはreferences型とします。

docker-compose run api rails g scaffold Task name:string description:text due_date:date completed:boolean user:references

RSpecでのテスト

factory botの利用

spec/factories/tasks.rb
require "faker"

FactoryBot.define do
  factory :task do
    name { Faker::Lorem.word }
    description { Faker::Lorem.sentence(word_count: 5) }
    due_date { Faker::Date.forward(days: 365) }
    user_id { nil }
    assignee_id { nil }
  end
end

こんな感じでfactorybotのfactoryを書いておくと,例えば

@user = create(:user)
@task = create(:task, user_id=@user.id)

とするだけでtaskを作成してデータベースに登録できます。
なお,この際fakerを使うことでランダムなテストデータを生成できます。

こんな感じでfactoryを書いておくことで,例えばtaskを読むためのテストを書くときに

spec/requests/task_read_spec.rb
require "rails_helper"

RSpec.describe "read a task", type: :request do
  # create a user
  before(:each) do
    # create a user
    @user = create(:user)
    # login
    post login_path, params: { email: @user.email, password: @user.password }, as: :json
    # create a task
    @task = create(:task, user_id: @user.id)
  end
  
  # テスト
end

こんな感じで書いておくと,テスト実行前にデータベースにタスクを登録でき,タスクを読むための実装に集中できます。
なお,letを使って遅延評価を行うこともできます。

shoulda-matchersによるアソシエーションのテスト

例えばTaskがUserに所属するという一対多の関係のテストはこのように簡単に書くことができます。

spec/models/task_spec.rb
require "rails_helper"

RSpec.describe Task, type: :model do
  describe "associations" do
    it { should belong_to(:user) }
  end
end

pry-railsによるデバッグ

htmlのviewを生成しないAPIモードでの開発では,pry-railsによるデバッグが有効です。

rubyファイルのどこかに

binding.pry

と書いておくとそこがブレークポイントとなり,コンソールが起動してその時点でのモデルの状態等を確認できます。
これはRSpecでのテスト時にも有効です。
RSpec内にブレークポイントを貼るとresponseのjsonの中身を確認することも可能です。
こうしたツールを使うことでcurlでは手が届かない部分に関してもデバッグが可能となります。

最後に

いかがだったでしょうか。
RailsでのAPI開発の参考になれば嬉しいです。

もしもっとこうしたほうがいいなどのアドバイスがございましたらぜひコメントで教えてください。

最後までお読みいただきありがとうございました。

Discussion