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日) ※緊急事態宣言により休業致します。" } }, ... ... ]
以上 なんか間違ってたりしたら教えてくれると嬉しいです。