[小ネタ] JbuilderでMissing Template Error
はじめに
Ruby on RailsにてJbuilderを使用してJSONを返却するControllerを開発中、RSpecからControllerを呼び出した際に以下のエラーに遭遇しました。
ActionView::MissingTemplate: Missing template ・・・
ご存知の人にとっては簡単な話だとは思いますが、意外にはまったので、備忘録として載せておきます。
原因と検証
結論からいうと、原因はControllerを呼び出す際にフォーマットとしてJSONを指定していなかったことです。
検証のためのソースを書いたので、動きを確認してみたいと思います。
Controller
class TopController < ApplicationController def index end end [/ruby] <p> 検証用なので、Controllerは何もせず、以下のViewフォーマット(今回はJSON)を返却するだけです。 </p> <h4>Jbuilder</h4> <p> こちらも検証のため、固定値をJSON形式で返すだけにしています。 </p> <h4>RSpec</h4> <p> 先ずはエラーを起こしたときのソースを書きたいと思います。 </p> require 'spec_helper' describe TopController do render_views describe "GET 'index'" do it 'get json' do get 'index' response.should be_success body = response.body json = JSON.parse(body) expect(json['title']).to eq("Top#index") expect(json['message']).to eq("Find me in app/views/top/index.html.erb") end end end
このテストを実行すると、タイトル通りのエラーが発生し、以下のようなメッセージがコンソールに表示されます。
ActionView::MissingTemplate: Missing template top/index, application/index with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:erb, :builder, :raw, :ruby, :jbuilder, :coffee]}. Searched in:
因みに4行目の「render_views」を書かないと、Controllerを呼び出した結果の「response.body」が空になります。
このテストを実行するためには、8行目を以下のように記述し、フォーマットとしてJSONを指定します。
get 'index', { :format => 'json' }
8行目を書き換えた状態でテストをすると、コンソールに以下のように表示され、テストが正常に実行できたことが分かります。
1 example, 0 failures, 1 passed Finished in 0.110006 seconds
ブラウザ
上記にも書いたとおり、原因はControllerを呼び出す際にフォーマットとしてJSONを指定していなかったことです。
なのでブラウザにてURLを指定し、Controllerを呼び出す際にも同様のことが起きるかを試してみました。
先ずはURLにてフォーマットを指定しないと・・・
次にURLにてフォーマットを指定すると(.jsonをつける)・・・
と、無事にJSONを表示できました。
まとめ
JbuilderにてJSONを返却する際には、リクエストを出す側(RSpecやブラウザ)もフォーマットを指定する必要があることが分かりました。
分かってしまえば単純なことですが、RSpecを先に書くテスト駆動的な開発を行っていたためか、以外に解決に時間が掛かりました。
P.S. 解決に協力して下さった先輩、ありがとうございました。
参考記事
Getting rspec to test controllers rendering JSON views
jayncoke / gist:4a7c1a67fdc464ad66e8