Rails 4 - 从视图中呈现JSON

时间:2013-09-04 18:24:59

标签: ruby-on-rails json rspec ruby-on-rails-4

我有最糟糕的时间从我的控制器渲染.json.erb文件,同时能够使用RSpec进行测试。我有api_docs / index.json.erb和以下控制器:

class ApiDocsController < ApplicationController
  respond_to :json

  def index
    render file: 'api_docs/index.json.erb', content_type: 'application/json'
  end
end

显式render file行似乎没必要,但如果我不这样做或render template: 'api_docs/index.json.erb',那么我会收到有关“Missing template api_docs / index”的错误。同样,如果我必须传递文件名,那就更糟糕了,我必须提供确切的目录--Rails应该知道我的ApiDocsController模板存在于api_docs目录中。

如果我有render filerender template,那么我可以访问该页面并按预期获取index.json.erb文件的JSON内容。但是,这个RSpec测试失败了:

let(:get_index) { ->{ get :index } }

...

describe 'JSON response' do
  subject {
    get_index.call
    JSON.parse(response.body)
  }

  it 'includes the API version' do
    subject['apiVersion'].should_not be_nil
  end
end

JSON.parse(response.body)行失败,如果我raise response.body,则为空字符串。如果我在控制器中执行render json: {'apiVersion' => '1.0'}.to_json,则测试通过就好了。

那么,当我转到/ api_docs时(无需将.json放在URL的末尾),我怎样才能始终呈现JSON模板,并且在浏览器和我的浏览器中都可以使用RSpec测试?我是否可以渲染模板而无需进行长render次调用,我可以在其中传递视图的完整路径?

2 个答案:

答案 0 :(得分:0)

实际上,由于您已经在控制器中使用respond_to :json,因此您只需使用render方法来选择模板,并且您可能知道,如果模板具有相同的控制器名称你应该能够抑制整个render方法的方法。

如果您只删除render行,结果是什么?

答案 1 :(得分:0)

我的部分解决方案基于this answer另一个问题:将defaults: {format: :json}添加到我的路径文件中,让我转到/ api_docs并在动作仅为def index ; end时查看JSON没有render。但RSpec测试仍然失败。我的路线文件中的完整行:resources :api_docs, only: [:index], defaults: {format: :json}

感谢this guy遇到同样的问题和his gist,我将render_views添加到了我的describe块,并让我的测试通过了:

describe ApiDocsController do
  render_views

  ...

  let(:get_index) { ->{ get :index } }

  describe 'JSON response' do
    subject {
      get_index.call
      JSON.parse(response.body)
    }

    it 'includes the API version' do
      subject['apiVersion'].should_not be_nil
    end
  end