ひびきの技術メモ帳

駆け出しエンジニアのメモ帳

ActiveModelSerializersを使ってみたメモ

事前準備

安定板って書いてあったので0.10.0を選択 gem 'active_model_serializers', '~> 0.10.0' gemを追加しで$ bundle GitHub - rails-api/active_model_serializers at 0-10-stable

rails g serializer Log(使いたいモデル名で読み替えてください)

app/serializers/log_serializer.rbが生成されるのでここに設定を書きます。

使い方

モデルサンプル

class Log < ApplicationRecord
  belongs_to :user
  belongs_to :grnv_bar_info
end
# ユーザーの立ち寄り情報
class CreateLogs < ActiveRecord::Migration[6.0]
  def change
    create_table :logs do |t|
      t.string :user_id
      t.string :grnv_bar_info_id
      t.text :memo
      t.date :drank_on


      t.timestamps
    end
  end
end
# お店情報
class CreateGrnvBarInfos < ActiveRecord::Migration[6.0]
  def change
    create_table :grnv_bar_infos do |t|
      t.string :grnv_id
      t.string :address
      t.string :name
      t.text :image
      t.text :grnv_url
      t.string :opentime
      t.string :holiday
      t.string :tel

      t.timestamps
    end
  end
end

log_serializer.rbを書く

class LogSerializer < ActiveModel::Serializer
  attributes :id, :grnv_bar_info_id, :drank_on
  attribute :created_at, key: :visited_on
  belongs_to :grnv_bar_info
  class GrnvBarInfoSerializer < ActiveModel::Serializer
    attributes :id, :name, :address, :grnv_url, :tel, :opentime, :holiday
  end
end

アソシエーション先の情報も一緒に取りたい場合はなかにclassを書いて取りたい情報を定義する。 active_model_serializers/getting_started.md at v0.10.6 · rails-api/active_model_serializers · GitHub

api/v1/logs_controller.rb

module Api
  module V1
    class LogsController < ApplicationController
      def index
        # logs = Log.all
        logs = logs.eager_load(:grnv_bar_info)
        render json: logs
      end
    end
  end
end

logs = Log.allで定義してもアソシエーション先の情報は取れるがN+1問題が発生するのでincludeしといた方が良さげ

Started GET "/api/v1/logs" for ::1 at 2021-02-14 20:48:28 +0900
Processing by Api::V1::LogsController#index as HTML
  Log Load (0.4ms)  SELECT `logs`.* FROM `logs`
  ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.6ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 1 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.4ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 2 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.5ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 3 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.4ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 4 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.4ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 5 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.5ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 6 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.3ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 7 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.5ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 8 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   CACHE GrnvBarInfo Load (0.0ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 6 LIMIT 1  [["id", 6], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.5ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 9 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.9ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 10 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   CACHE GrnvBarInfo Load (0.0ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 8 LIMIT 1  [["id", 8], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   CACHE GrnvBarInfo Load (0.0ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 2 LIMIT 1  [["id", 2], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   CACHE GrnvBarInfo Load (0.0ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 1 LIMIT 1  [["id", 1], ["LIMIT", 1]]
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.4ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 11 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers]   GrnvBarInfo Load (0.3ms)  SELECT `grnv_bar_infos`.* FROM `grnv_bar_infos` WHERE `grnv_bar_infos`.`id` = 12 LIMIT 1
[active_model_serializers]   ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Attributes (96.49ms)
Completed 200 OK in 120ms (Views: 102.0ms | ActiveRecord: 13.4ms | Allocations: 43767)


Started GET "/api/v1/logs" for ::1 at 2021-02-14 20:49:52 +0900
Processing by Api::V1::LogsController#index as HTML
  SQL (0.4ms)  SELECT `logs`.`id` AS t0_r0, `logs`.`user_id` AS t0_r1, `logs`.`grnv_bar_info_id` AS t0_r2, `logs`.`memo` AS t0_r3, `logs`.`drank_on` AS t0_r4, `logs`.`created_at` AS t0_r5, `logs`.`updated_at` AS t0_r6, `grnv_bar_infos`.`id` AS t1_r0, `grnv_bar_infos`.`grnv_id` AS t1_r1, `grnv_bar_infos`.`address` AS t1_r2, `grnv_bar_infos`.`name` AS t1_r3, `grnv_bar_infos`.`image` AS t1_r4, `grnv_bar_infos`.`grnv_url` AS t1_r5, `grnv_bar_infos`.`grnv_tel` AS t1_r6, `grnv_bar_infos`.`opentime` AS t1_r7, `grnv_bar_infos`.`holiday` AS t1_r8, `grnv_bar_infos`.`tel` AS t1_r9, `grnv_bar_infos`.`created_at` AS t1_r10, `grnv_bar_infos`.`updated_at` AS t1_r11 FROM `logs` LEFT OUTER JOIN `grnv_bar_infos` ON `grnv_bar_infos`.`id` = `logs`.`grnv_bar_info_id`
  ↳ app/controllers/api/v1/logs_controller.rb:6:in `index'
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Attributes (10.15ms)
Completed 200 OK in 53ms (Views: 42.4ms | ActiveRecord: 6.1ms | Allocations: 23893)

上がlogs = Log.all 下がlogs = Log.eager_load(:grnv_bar_info)

出力はこんな感じ

[
{
"id": 1,
"grnv_bar_info_id": "1",
"drank_on": "2021-01-29",
"visited_on": "2021-01-29T23:09:10.489Z",
"grnv_bar_info": {
"id": 1,
"name": "スターバックスコーヒー 志木駅前店",
"address": "〒352-0001 埼玉県新座市東北2-39-1 井下田第2ビル1F",
"grnv_url": "https://r.gnavi.co.jp/d02rspn80000/?ak=nwVBjKQQ4uWSWaNOcvOMy9gHVwn5m6xty%2FXZK2fnwrE%3D",
"tel": "048-476-0551",
"opentime": "月~金 07:00~22:00 土・日・祝日 08:00~22:00",
"holiday": "年中無休"
}
},
{
"id": 2,
"grnv_bar_info_id": "2",
"drank_on": "2021-01-29",
"visited_on": "2021-01-30T00:50:08.186Z",
"grnv_bar_info": {
"id": 2,
"name": "肉バル&和風居酒屋HAL",
"address": "〒352-0001 埼玉県新座市東北2-39-8 永代ビル4F",
"grnv_url": "https://r.gnavi.co.jp/et3pc1r20000/?ak=nwVBjKQQ4uWSWaNOcvOMy9gHVwn5m6xty%2FXZK2fnwrE%3D",
"tel": "050-5488-3333",
"opentime": "月~日・祝前日・祝日 18:00~翌1:00(L.O.24:00、ドリンクL.O.24:30)",
"holiday": "毎週木曜日 その他(2021年1月12日~2021年2月7日) ※緊急事態宣言により休業致します。"
}
},
...
...
]

以上 なんか間違ってたりしたら教えてくれると嬉しいです。