きっかけ
controller
の返り値をjson
形式で返却する時、モデルで定義されているattributes
しか返すことができません。そんな時、他のattributes
を追加する方法が分からず困ることがあったので、備忘録として残します。
attributeを追加する
render json:
に、methodsオプション
をつけ、model
で定義したメソッドを呼び出す。
使い方
例えば・・・
以下のようなモデルがあったとする。
create_table "users", force: :cascade do |t|
t.string "first_name", null: false
t.string "last_name", null: false
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
end
で、以下のようにでActiveRecord
で見つけたuser
オブジェクトの結果をjson
形式で返す場面があったとする。
user = User.find_by(id: 1)
render json: user
# 返り値
{
data: {
id: 1
first_name: "山田",
last_name: "太郎",
updated_at: "2022-09-20T23:34:11.502Z",
created_at: "2022-09-11T06:11:08.726Z"
},
status: 200,
config: {・・・},
・・・
}
この返却値の中にモデルメソッドの処理結果を追加したい。
例えば、以下のようにモデルで、User
のfull_name
を取得するメソッドがあったとする。
これを先程のjsonデータ
に含めたい。
class User < ApplicationRecord
def full_name
first_name + ' ' + last_name
end
end
以下のようにmethodsオプション
を追記することで、full_name
はattribute
じゃないにもかかわらず、他のattribute
と同じようにHash
に取り込まれます。
user = User.find_by(id: 1)
render json: user, methods: :full_name
# 返り値
{
data: {
id: 1
first_name: "山田",
last_name: "太郎",
updated_at: "2022-09-20T23:34:11.502Z",
created_at: "2022-09-11T06:11:08.726Z",
full_name: "山田 太郎"
},
status: 200,
config: {・・・},
・・・
}
Railsガイドに書かれている通り、ActiveRecord
はActiveModel::Serializationモジュール
を自動でinclude
しているので、インスタンスメソッドである、as_json
やmethodsオプション
が何もせずとも使えるようです。
そのため、以下のように書いても同様の結果が得られます
user = User.find_by(id: 1)
render json: user.as_json(methods: :full_name)
必要のないattributeを排除する
こちらもドキュメントに書かれている通り、only
オプションを追加することで必要なattribute
を絞ることができます。他にもオプションが用意されているので状況に応じて使い分けることができます。
user = User.find_by(id: 1)
render json: user, only: [:id, :first_name]
# 返り値
{
data: {
id: 1,
first_name: "山田"
},
status: 200,
config: {・・・},
・・・
}
参考にした記事
Rails における JSON のシリアライズと向き合う 🦜
最後に
ここまでご覧いただきありがとうございます。m(_ _)m
備忘録のつもりで書きましたが、誰かのお役に立てば嬉しく思います。