active_model_serializers

active_model_serializers

active_model_serializers

Ruby on RailsでJSONを整形してくれるライブラリです。
実用性という点では評価してないですが、チョロっと触ったところでは結構便利なので取っ掛かりだけでも。

導入

Gemfileに以下を追加。

gem 'active_model_serializers', '~> 0.10.0'

そして以下。

> bundle install

使い方

active_modelと冠しているだけあってモデル(テーブル)と密接に関係してます。
modelsディレクトリにuser.rbがある場合はserializersディレクトリにuser_serializer.rbを作って、userテーブルのカラムからJSONを加工といった流れですかね。
とはいえテーブルと必ず紐づいている必要はなく完全に独立したserializerも作れます。実際にやってみた方が早いですね。
まず以下のテーブルがあるとします。

Railsでmodelsに以下のように作成されているものとします。

user.rb

class User < ApplicationRecord
  has_one :user_attribute
end

user_attribute.rb

class UserAttribute < ApplicationRecord
  belongs_to :user
end

active_model_serializers導入後ならserializerコマンドが使えるようになっていますので上記のmodelのserializerを作成します。

> rails g serializer user
> rails g serializer user_attribute

これでserializersというディレクトリと以下のファイルが作成されます。

user_serializer.rb
user_attribute_serializer.rb

必ずしもmodelと同名でなくても構いません。modelと同名の場合は紐づけされ (render使う時に省略型が使えるだけ) ます。

userとuser_attributeは1:1になってます。
showされた場合は以下のようなJSONで返したいとします。

{
  "id": 1,
  "name": "テスト01",
  "attr":{
    "user_attribute_id": 1,
    "phone": "07011112222",
    "memo": "テスト"
  }
}

この場合はserializerを以下のように編集します。

user_serializer.rb

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name
  has_one :user_attribute, key: :attr
end

user_attribute_serializer.rb

class UserAttributeSerializer < ActiveModel::Serializer
  attribute :id, key: :user_attribute_id
  attributes :phone, :memo
end

各シリアライザにはUserとUserAttributeのオブジェクトが渡されます。
そのフィールドから出力したいものをattributesで指定します。
元のフィールド名を変更したい場合はattributeで key: を指定すれば変更できます。
has_oneのように親子関係を指定できます。こちらも名前を変更したい場合は key: が指定できます。

後はコントローラですが通常なら以下のようにJSONで返すためのハッシュを自前で容易する必要がありました。

@User = User.find(1)
@UserAttr = @User.user_attribute
render json: {
  id: @User.id,
  name: @User.name,
  attr: {
    user_attribute_id: @UserAttr.id,
    phone: @UserAttr.phone,
    memo: @UserAttr.memo
  }
}

これがactive_model_serializersが導入されている場合は以下で済みます。

@User = User.find(1)
render json: @User

これで@User (user.rb) に紐づいているuser_serializer.rbが呼び出されで同じ結果のJSONが返されます。

serializerがmodelと同じ名前なら勝手に呼び出されます。

User -> UserSerializer

でも以下のようにすれば別のserializerも呼び出せます。

@User = User.find(1)
render json: @User, serializer: UserXXXXSerializer

上記は単数の場合、複数データを配列で返したい場合は以下です。

@Users = User.all
render json: @Users, each_serializer: UserXXXXSerializer

コードがスッキリしてモデルに対してJSONを紐づけできるので便利です。
ちなみにこちらの方が処理的にも早いらしいです。

項目を追加したいとか加工したいとか

selializerでJSONの項目を追加したり加工したりできます。
例えば現在日時を追加したい場合は :current_datetime を追加。
nameに必ず「様」を付けたい場合は :name_sama を追加。
そして同名のメソッドを追加します。

user_serializer.rb

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name
  has_one :user_attribute, key: :attr
  attributes :current_datetime, :name_sama

  def current_datetime
    Time.now
  end

  def name_sama
    object.name + "様"
  end
end

objectにはrender json: で渡されたものが入ってます。

has_oneなどで別のserializerを使いたい場合

serializerで指定すればOKです。

class UserSerializer < ActiveModel::Serializer
  attributes :id, :name
  has_one :user_attribute, key: :attr, serializer: :UserAttributeXXXXSerializer

コメント

このブログの人気の投稿

AmazonSAMでnode20.xを使う

ボタンとタイマー

KiCadでシンボルを作る