0
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 3 years have passed since last update.

RailsでJbuilderを使ってJSONフォーマットを出力する

Posted at

この記事について

RailsのActiveViewではブラウザに表示させるHTML形式以外に、JSONでのデータ出力などが簡単にできます。
しかし、簡単なはずのJSONデータ出力にハマった経験を共有させていただきたいと思います。

jbuilderテンプレートを置いたのに、レンダリングに使われない??

Railsガイド-Action Viewの概要にしたがって、
jbuilderのテンプレートファイルを置いたのに、以下のようにテンプレートが読まれた結果にならず、どハマりしました。

前提

この記事は、以下のようなアプリケーション構成を前提に記載させていただきます。

項目
アプリケーション名 apptest
モデル名 sample
view名 index
モデルの属性 title:string, description:string

テンプレートファイルの内容

モデルの内容に関係のないものを出力する中身のない簡単なテンプレートを作りました。
※ここでは、apptest/app/views/samples/index.json.jbuilderというファイル名で記載しています。

index.json.jbuilder(テンプレートファイル)
json.test("hoge")

予期していた結果はこちら。

前出のRailsガイドによれば、apptest/samples/index.jsonにアクセスすれば以下のようなご回答をいただけるものと思っていたのですが。。

result-expected
{
  "test": "hoge"
} 

実際の結果

しかし、実際に取得できたのは以下のようにSampleモデルのデータそのもの。

result-actual
[{"id":1,"title":"test","description":"sample","created_at":"2020-05-06T05:54:20.885Z","updated_at":"2020-05-06T05:54:20.885Z"}]

原因

scaffoldで生成されたコントローラは以下のような内容になりますが、
このままだと、変数@samplesの内容をjson形式にしたものがレンダリングされてしまうためでした。

samples_controller.rb
class SamplesController < ApplicationController
  def index
    @samples = Sample.all();

    respond_to do | format |
      format.html # index.html.erb
      format.xml  { render xml: @samples }
      format.json { render json: @samples } # <== ここです!
    end
  end
end

解決!!

renderさんに、「ちゃんと"index"というテンプレートがあるんだよ」と教えてあげます。

samples_controller.rb
class SamplesController < ApplicationController
  def index
    @samples = Sample.all();

    respond_to do | format |
      format.html # index.html.erb
      format.xml  { render xml: @samples }
      format.json { render :index }  # renderにindexのテンプレートを使うように指定
    end
  end
end

どう言うことか?

自分の理解不足により、家で2時間くらい悩み続けてしまいましたが、
render json:render xml:という書き方は、後ろに指定した変数の内容を指定した形式に変換して出力するという意味になるんですね。
render テンプレート名とすることで、指定したテンプレートを使用した出力を行ってくれます。

ちなみに、今回の場合は以下の書き方でもうまく動きました。
よく考えたら、デフォルトではコントローラのメソッド名(ここではindex)と同じ名前のテンプレートを勝手に使ってくれるんでしたね。

samples_controller.rb(これでもいける)
class SamplesController < ApplicationController
  def index
    @samples = Sample.all();
    respond_to do | format |
      format.json
    end
  end
end
0
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
0
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?