【Rails API】1対多のテーブルからデータを取得

プログラミング

Rubi on RailsのAPIで1対多のテーブルからいい感じでデータを取得したい

今回は、このような問題を解決する内容となっています。

▼Railsの以下のGemを使用して、データを返すような作りにしていきます。

gem 'active_model_serializers'

Rails APIの開発環境が完了しているというのが、前提条件です。以前に記事で環境構築しているので、ご覧になってみてください。

この記事の対象は、以下のような人になります。

  1. Railsをはじめた初心者の人
  2. 簡単なRails APIを作ってみたい人

Rails初心者の人でAPIを簡単に作ってみたい人は最後までご覧になってください。

本記事の信頼度

・エンジニア歴10年以上
・IT企業転職歴も3回以上
・プログラミングスクール運営側の経験あり
・現在はフリーランスエンジニアとして企業に常駐(在宅勤務)



目次

  1. 1対多のテーブル作成
    • ユーザーテーブルとグループテーブルの関係
    • ユーザーが所属するグループのテーブル
    • ユーザーが登録されるテーブル
  2. Rails APIの設計
    • active_model_serializersのGemを追加
    • routesの作成
    • modelの作成
    • controllerの作成
    • serializerを追加
  3. Jsonをカスタマイズできる
    • attributesにcreated_atを追加
    • attributesにカスタマイズしたデータを追加
  4. まとめ

1対多のテーブル作成

rails01

2つのテーブルを作っていきます。

  • ユーザーが所属するグループのテーブル
  • ユーザーが登録されるテーブル

ユーザーテーブルとグループテーブルの関係

以下のような関係になります。

1

グループ

id 1
グループ名 グループ1

ユーザー

id 1
group_id 1
name たかはし
id 2
group_id 1
name さいとう

ユーザーが所属するグループのテーブル

グループ名が登録されるテーブルです。一つのグループに複数のユーザーが紐づくというイメージになります。

create_table "groups", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
  t.string "group_name"
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
end

ユーザーが登録されるテーブル

ユーザーが登録されるテーブルです。ユーザーテーブルにグループのIDを持っている状態です。あとは名前。

create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
  t.bigint "group_id"
  t.string "name"
  t.datetime "created_at", precision: 6, null: false
  t.datetime "updated_at", precision: 6, null: false
  t.index ["group_id"], name: "index_users_on_group_id"
end

Rails APIの設計

rails02

設計といっても、グループを取得した時に紐づくユーザーも一緒に取得するというAPIを作ります。

active_model_serializersのGemを追加

最初にGemfileに以下のGemを追加しておきます。

gem 'active_model_serializers'

bundle installをします。

// apiはサービス名です
docker-compose run api bundle install

routesの作成

よくある一覧ページ用のAPIです。

// こちらで取得できるようなイメージです。
// http://localhost:5000/api/v1/groups

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :groups, only: :index
    end 
  end 
end

modelの作成

has_manyの記述を忘れずに。グループ名に文字制限のバリデーションを追加

Group

class Group < ApplicationRecord

  has_many :users

  validates :group_name, presence: true, length: { maximum: 140 }
end

こちらにはbelongs_toの記述を忘れずに。ユーザー名に文字制限のバリデーションを追加

User

class User < ApplicationRecord

  belongs_to :group

  validates :name, presence: true, length: { maximum: 140 }
end

controllerの作成

以下のGemが追加される前のコントローラーになります。

class Api::V1::GroupsController < ApplicationController

  def index
    render json: { group: Group.all, status: 200 }
  end

end

APIを叩いてみます。

curl -X GET http://localhost:5000/api/v1/groups

結果

{
  "group": [
    {
      "id": 1,
      "group_name": "グループ1",
      "created_at": "2021-07-10T00:00:00.000Z",
      "updated_at": "2021-07-10T00:00:00.000Z"
    }
  ],
  "status": 200
}

serializerを追加

active_model_serializersを追加して、コードの改修していきます。

gem 'active_model_serializers'

Serializerを追加

GroupSerializer

class GroupSerializer < ActiveModel::Serializer
  attributes :id, :group_name

  has_many :users
end

UserSerializer

class UserSerializer < ActiveModel::Serializer
  attributes :id, :group_id, :name

  belongs_to :group
end

コントローラーを改修

GroupsController

class Api::V1::GroupsController < ApplicationController

  def index
    groups = Group.all
    render json: groups, include: [:users], status: 200
  end

end

APIを叩いてみます。

curl -X GET http://localhost:5000/api/v1/groups

結果

[
  {
    "id": 1,
    "group_name": "グループ1",
    "users": [
      {
        "id": 1,
        "group_id": 1,
        "name": "たかはし"
      },
      {
        "id": 2,
        "group_id": 1,
        "name": "さいとう"
      }
    ]
  }
]

同じグループに紐づくユーザーが一緒に取得できていれば、成功です。

Jsonをカスタマイズできる

rails03

active_model_serializersで出力する内容を簡単にカスタマイズできます。

attributesにcreated_atを追加

上記でセットしたGroupSerializerでは、attributesにはid, group_nameがセットされています。

例えば、attributesにcreated_atを追加して作成日を取得することができます。

GroupSerializer

class GroupSerializer < ActiveModel::Serializer
  attributes :id, :group_name, :created_at

  has_many :users
end

attributesにカスタマイズしたデータを追加

グループ名に敬称「様」を追加して返却するようカスタマイズできました。

GroupSerializer

class GroupSerializer < ActiveModel::Serializer
  attributes :id, :group_name, :created_at, :add_honorifics

  has_many :users

  def add_honorifics
    "#{object.group_name}様"
  end

end

まとめ

今回はRails APIの作成とGEM「active_model_serializers」を使い、返却するデータを簡単にカスタマイズするという内容を紹介してきました。

Rails APIの学習をしている方はぜひ使ってみてください。

独学での学習がつらくなってきたという場合は、挫折する前にメンターを頼むかプログラミングスクールなどで指導を受けることをおすすめします。

当サイトで申込の多いプログラミングスクール

TechAcademyの無料体験
マンツーマンでオリジナルアプリの作成ができるテックアカデミーは人気が高いプログラミングスクール。
Webエンジニア輩出実績トップクラスの【ポテパンキャンプ】
転職に強く本気でエンジニア転職を目指す人におすすめ。難易度が高いため身につくスキルも高く企業からの評価も高いのが特徴。
CodeCamp無料体験
講師を選択できるのが特徴のコードキャンプ。チャットでの質問ができないと言われていますが、オプションでチャットサポートを選択できるのがあまり知られていない。講師の評判が高いため質問しながらどんどん進みたい人向け。