【rails】複数のjsonデータを返す方法

発生経緯

railsアプリを作る時、Vue.jsを使うと基本的にrailsのデータはAPIで返すことになる。 ということは最後の出力をjson形式で返すことになるわけだが、ここでかなりつまづいたので忘れないようにメモしておく。

単体jsonデータの場合

class QuestionsController < ApplicationController
  def index
    @question = Question.new
    @questions = Question.all.order(created_at: "DESC")
    respond_to do |format|
      format.html
      format.json
    end
  end
end

QuestionテーブルはUserテーブルと紐づいており、Questions(多):User(1)の関係になっている。この時 index.json.jbuilder を使うとこんな感じになる。

json.array! @questions, :title, :content, :user

一応これで@questionsに関連したUserもjson形式で送ることはできた。が、これだけのためにjbuilderを使うのはもったいない。

そこで、Controllerの方でまとめてみる。

class QuestionsController < ApplicationController
  def index
    @question = Question.new
    questions = Question.all.order(created_at: "DESC")
    respond_to do |format|
      format.html
      format.json { render json: questions, include: [:user] }
    end
  end
end

includeを使うことで、関連したテーブルのデータも送ることができるようになる。jsonの中身を確認すべくhtml端子を .json にしてみる。

[{"id":1,"title":"hoge","content":"huga","user_id":1,"created_at":"2019-10-14T10:33:14.247+09:00","updated_at":"2019-10-14T10:33:14.247+09:00","user":{"id":1,"email":"hoge@gmail.com","created_at":"2019-10-13T16:58:27.516+09:00","updated_at":"2019-10-13T16:58:27.516+09:00","name":"foo"}}]

ちょっと見辛いが、questionのuser_idに紐づいたUserのデータが一緒に入っているのがわかる。

複数のjsonデータの場合

では、showメソッドでquestionに紐づいたanswerも一緒に送るにはどうすれば良いか?

class QuestionsController < ApplicationController
  def show
    @question = Question.find(params[:id])
    @answers = Answer.where(question_id: params[:id]).order(created_at: "DESC")
    @answer = Answer.new
    respond_to do |format|
      format.html
      format.json
    end
  end
end

ここで得たいのはquestionのデータとanswersのデータ。 ひとまず show.json.jbuilder に書いてみる。

json.question @question, :title, :content, :user
json.answers do
  json.array! @answers, :text, :user
end

複数の時も上のようにcontrollerにまとめるには .to_jsonを使うとできなくはないが、Vueで受け取ったデータに \ が死ぬほど入ってきた…

まとめ

単体jsonデータはcontrollerにまとめることができたけど、複数のデータのまとめかたがいまいちわからなかった…ここは忘れずに改善する必要がある。