プログラミング技術

本サイトはプロモーションが含まれています。

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

rails-api-sample
初心者さん
Rubi on RailsのAPIで1対多のテーブルからいい感じでデータを取得したい

このような疑問をお持ちの方に向けて書いています。

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

gem 'active_model_serializers'

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

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

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

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

この記事を書いた人

くろめがね

特別何か持っているわけではない普通の人が未経験からエンジニアに転職し、10年以上経験を積みフリーランスエンジニアになり、単価80万〜140万の案件に参画し稼げるように。プログラミングを始めた頃は、「プログラミング向いていないかも」、「自分のスキルレベル低い」と感じ悩んだ経験がある。

  • 元プログラミングスクール運営企業の社員のためプログラミングの学習に詳しい
  • 自分と同じように悩んでいる初心者へのアドバイスが得意。

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の学習をしている方はぜひ使ってみてください。

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

-プログラミング技術