##概要
こんにちは。
今回は始めてRailsでAPIを作成してみたのでその備忘録を残したいと思います。
以下を使いました。
-
ツール
-
Postman(レスポンスを確認するためのツール)
-
gem
-
active_model_serializers
今回はUserを管理できるAPIを作ります。
事前にこちらの記事を読んで作成しております。
https://qiita.com/Kaki_Shoichi/items/d4adcf0298ed0b4614a2
https://qiita.com/c5meru/items/1c921676de8a5a038f70
https://qiita.com/yyh-gl/items/30bd91c2b33fdfbe49b5
##仕様
-
jobテーブルとuserテーブルは1対多の関係にある。
-
jobとuserを登録できる。
-
userはjob_idを外部キーに持つ
-
job_nameとusernameというリクエストを送る
-
すでにjob_nameが存在しているときはそのIDを外部キーに、job_nameがない場合は新しくjobを作成しそのidを外部キーとする。
-
user一覧を取得できる。
-
リクエストにvalueを含めない場合は全てのuserを表示させる。
-
リクエストにjob_nameを指定した場合は該当するuserのみを表示させる。
以上の仕様で作成したいと思います。
それでは早速始めていきます。
##導入
まずはapiモードでRailsを作成してください。
$ rails new testapi --api
以下のgemをインストールします。
gem 'active_model_serializers'
テーブル作成
以下のようにテーブルとカラムを作成します。
create_table "jobs", force: :cascade do |t|
t.string "name", null: false
t.index ["name"], name: "index_jobs_on_name", unique: true
end
create_table "users", force: :cascade do |t|
t.text "username", null: false
t.integer "job_id", null: false
t.index ["job_id"], name: "index_users_on_job_id"
end
モデル
モデルのバリデーションは次のようにしました。
class Job < ApplicationRecord
has_many :users, dependent: :destroy
validates :name, uniqueness: true, presence: true
end
class User < ApplicationRecord
belongs_to :job
validates :username, presence: true
validates :job_id, presence: true
end
ルーティング
api作成時はバージョン管理しやすい設計が推奨されているようです。
また今回はusers_contorollerのみを使用して機能実装を行います。
Rails.application.routes.draw do
namespace 'api' do
namespace 'v1' do
resources :users, only: [:create, :index]
end
end
end
コントローラ
users_controllerはこのように作成致しました。
module Api
module V1
class UsersController < ApplicationController
before_action :set_job
def create
@job = Job.create(name: user_params[:job_name]) if @job.blank?
user = User.new(username: user_params[:username], job_id: @job.id)
if user.save
render status: :created, json: { status: 201 }
else
render status: :unprocessable_entity, json: { status: 422 }
end
end
def index
if user_params[:job_name].nil?
users = User.all
render json: users
elsif @job.nil?
render status: :not_found, json: { status: 404 }
else
users = @job.users
render json: users
end
end
private
def user_params
params.permit(:username, :job_name)
end
def set_job
@job = Job.find_by(name: user_params[:job_name])
end
end
end
end
##レスポンスを整形
次にjsonで返すレスポンスを整形します。
導入でインストールしたactive_model_serializersを使用します。
※ 色々調べたのですが、現在は fast_json_apiというgemの方が推奨されているようです。使い方はほとんど変わらないようですが、レスポンスがシンプルだったので今回はamsを使用しました。
こちらの記事を参考にさせて頂きました。
https://qiita.com/m_nakamura145/items/75fd7c0934daf9bcc21d
使い方は以下の通りです。
まずはコマンドで必要なファイルを作成します。
$ rails generate serializer User
app/serializers/model_serializer.rbファイルが作成されます。
作成されたファイルを以下のように記述します。
class UserSerializer < ActiveModel::Serializer
attributes :id, :job, :username
belongs_to :job
def job
object.job.name
end
end
これでjsonレスポンスに独自のパラメータを追加して返すことができます。
##リクエスト
ではPostmanを使用してリクエストし、レスポンスをみてみます。
Postman
まずはルーティングを確認します。
$ rake routes
api_v1_ideas GET /api/v1/users(.:format) api/v1/users#index
POST /api/v1/users(.:format) api/v1/users#create
それではPostmanで上記URLにリクエストを送ってみます。(rails s してください。)
画像左上をpostに変更してください。
すると以下のようなレスポンスが得られました。
{
"status": 201
}
これでレコードを登録することができました。
次は作成したレコードを取得してみます。
画像左上をgetに変更してください。
[
{
"id": 1,
"job": "testjob1",
"username": "testuser"
}
]
先ほど登録したレスポンスを得られました。
ここでkey,valueを設定しない場合は登録している全てのレコードを取得することができます。
以上です。
APIの記事がそもそも少なかった事と、1対多関係にあるテーブルに独自のパラメータをリクエストする方法がなかなか見つからなかったのでかなり時間がかかりました。
お付き合い頂きありがとうございました。