2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

人生初のRailsでAPI作成しNext.jsに連携して表示に成功! ~postman経由です~

Last updated at Posted at 2023-07-28

はじめに

こんにちは!上野と申します!
これからRails + Next.jsで連携したデータの渡し方と受け取り方、
ビューに表示するやり方を身につけたので書きます!
実務未経験の人が書いたコードと知識なので鵜呑みにしないでください。。。

私は今レシピの原価計算が計算機なしでできるアプリを開発途中です

その中で学んだ事を書いていきます。

設定としてはAuth0で認証していて関係性は一つの仕入れ先に対して複数の原材料です。

まずは仕入れ先の登録から

postmanでこのようなリクエストボディを送れば登録できます。

{
    "supplier": {
        "name": "postmanから",
        "contact_info": "連絡先"
    }
}

レスポンス

{
    "supplier": {
        "id": 10,
        "user_id": "auth0|64b9c1cfb6c808c6f9ccd15e",
        "name": "postmanから",
        "contact_info": "連絡先",
        "created_at": "2023-07-28T08:53:07.481+09:00",
        "updated_at": "2023-07-28T08:53:07.481+09:00"
    }
}

登録はこれでok!!ですが表示は仕入れ先だけだと足りないのでsupplier#indexで
少しばかりJSONをいじる↓SuppliersController

def index
	suppliers = current_user.suppliers.includes(:ingredient).oldest
	render json: { suppliers: suppliers.map do |supplier|
	supplier.as_json(include: {
                        ingredeients: {},	
                        })
	end }, status: :ok
end

これで現在ログインしているユーザーが作成した仕入れ先と
多の関係である紐づいた原材料を効率良く、古い順で表示させるようsuppliers変数に代入
そしてfrontにjson形式でレスポンスを返すためにrenderで一覧なのでmapメソッドを使い繰り返し処理をし、as_jsonメソッドでカスタマイズできるjsonにしてから、原材料の情報もjsonで取得している。

↓取得結果

{
    "id": 10,
    "user_id": "auth0|64b9c1cfb6c808c6f9ccd15e",
    "name": "postmanから",
    "contact_info": "連絡先",
    "created_at": "2023-07-28T08:53:07.481+09:00",
    "updated_at": "2023-07-28T08:53:07.481+09:00"
    "ingredients": []
}

このようにsupplierからingredientsの空の配列が取得できているのが確認できる

ですがこのように複雑なjsonになってくると,パフォーマンスの関連で
不要なカラムは削ぎ落としたくなるのです

表示させるつもりのない、作成日と更新日を削ぎ落としましょう

コントローラ
def index
	suppliers = current_user.suppliers.oldest.select(:id, :user_id, :name, :contact_info).includes(:ingredients).map do |supplier|
		supplier.attributes.merge(
			ingredients: supplier.ingredients.select(:id, :supplier_id, :buy_cost, :buy_quantity, :unit, :name)
		)
	render json: { suppliers:}, status: :ok
	# ↑ショートカット記法で{ suppliers: suppliers }同じだったら{ suppliers:}このように省略できる。
end

これで先ほどと少々記述が複雑になりましたがcreated_atとupdated_atが削ぎ落とされました。

なぜsuppliers変数の段階で加工したかというとrenderから見た目をスッキリしたいのと後々モデルに移動しやすいからです。(最初の量だったらコントローラに記述でいいと思います)

selectメソッドを使うとDBから取得する前に、
ActiveRecordが不要なカラムを削ぎ落としてくれるのでこのアプローチにしました。

次にモデルにDB操作責務を渡します

理由はコントローラは、ビューからリクエストをもらい、上記のように、複雑な加工をしてから、
DBにお願いします。そして、DBから情報をもらい、ビューにレスポンスを返しと中間地点の役割を果たしています。
そこで、複雑な加工とDBにお願いと受け取る役割をモデルに渡すことによって、
コントローラはスッキリし、リクエストとレスポンスに集中できるというわけです!
Fat Model, Skinny Controllerの原則を意識しています

SupplierModel
def self.with_ingredients_for_user(user)
  user.suppliers.oldest.select(:id, :user_id, :name, :contact_info).includes(:ingredients).map do |supplier|
    supplier.attributes.merge(
      ingredients: supplier.ingredients.select(:id, :supplier_id, :buy_cost, :buy_quantity, :unit, :name)
    )
  end
end

引数にuserを持たせているのは、before_actionはアクションメソッド(コントローラ)が行われる前に行うことができるので、current_userはコントローラ内でしか使えないのがわかります。
なので引数にここはなんでもいいですが、わかりやすくuserです。
そして大事なのはクラスメソッドにしているところです。あとは、中身はそのまんまですね。

そしてコントローラに渡すとき↓

SuppliersController
def index
  suppliers = Supplier.with_ingredients_for_user(current_user)
  render json: { suppliers: }, status: :ok
end

(current_user)を渡してあげればいいのです!
めちゃくちゃスッキリしましたね!!

結果: suppliers#indexのAPIを叩くとレスポンスはこうなる

{
    "id": 10,
    "user_id": "auth0|64b9c1cfb6c808c6f9ccd15e",
    "name": "postmanから",
    "contact_info": "連絡先",
    "ingredients": []
}

はい!created_atとupdated_atがなくなりました!ちなみに表示させたい時はもちろんですが取得は必須です
今回の場合表示させる機会がないため削ぎ落としただけです。

次は原材料の作成です

リクエストボディはこんな感じです

{
    "ingredient": {
        "name": "サンプル原材料",
        "buy_cost": 1000,
        "buy_quantity": 500,
        "unit": "g",
        "supplier_id": 10
    }
}

レスポンスボディはこちら

"ingredient": {
	{
		  "id": 24,
		  "supplier_id": 10,
		  "buy_cost": "1000.0",
		  "buy_quantity": "500.0",
		  "unit": "g",
		  "name": "サンプル原材料",
		  "created_at": "2023-07-28T10:15:57.022+09:00",
		  "updated_at": "2023-07-28T10:15:57.022+09:00"
	}
}

因みにアクティブレコードのログではこれ
Parameters: {"ingredient"=>{"name"=>"サンプル原材料", "buy_cost"=>1000, "buy_quantity"=>500, "unit"=>"g", "supplier_id"=>10}}

そして先ほど作成した、suppliers#indexアクションのapiを叩くと

{
    "id": 10,
    "user_id": "auth0|64b9c1cfb6c808c6f9ccd15e",
    "name": "postmanから",
    "contact_info": "連絡先",
    "ingredients": [
        {
            "id": 24,
            "supplier_id": 10,
            "buy_cost": "1000.0",
            "buy_quantity": "500.0",
            "unit": "g",
            "name": "サンプル原材料"
        },
        {
            "id": 25,
            "supplier_id": 10,
            "buy_cost": "550.0",
            "buy_quantity": "500.0",
            "unit": "g",
            "name": "サンプル原材料2"
        }
    ]
}

はい〜!postmanからという名前の仕入れ先の原材料が表示できました〜!!
しっかりと作成日と更新日が削ぎ落とされてます

ビューで見るとこんな感じ、postmanで作成したデータが表示されています。

スクリーンショット 2023-07-28 10.24.31.png

無事表示に成功しました!!

次にポストマンではなくfront側のフォームから仕入れ先の送信できるようにします!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?