この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
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