【问题标题】:Rails 4 - rendering JSON from a viewRails 4 - 从视图渲染 JSON
【发布时间】:2013-09-08 09:24:58
【问题描述】:

我在从控制器渲染 .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',则会收到有关“缺少模板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' =&gt; '1.0'}.to_json,那么测试就可以通过了。

那么,当我转到 /api_docs 时,如何始终呈现 JSON 模板(无需将 .json 放在 URL 的末尾),并且以一种在浏览器和我的 RSpec 测试中都有效的方式?我是否可以渲染模板而不必进行一些长时间的render 调用,在其中我传递视图的完整路径?

【问题讨论】:

  • 我想知道这是否不能回答你的问题:stackoverflow.com/questions/10681816/…
  • 我在一分钟前发现它有帮助:我可以转到 /api_docs 而不是 /api_docs.json 并在浏览器中查看 JSON,但 RSpec 测试仍然失败,因为 response.body 是空字符串。
  • This RSpec issue 可能是相关的。

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


【解决方案1】:

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

如果只是去掉render这一行,结果如何?

【讨论】:

  • 转到 /api_docs 会导致 Missing template api_docs/index。我必须去 /api_docs.json。
  • 哦,我错过了你提到你也需要渲染一个 json 模板,抱歉。那么你应该可以说类似render 'api_docs/index.json'render 'index.json'
  • 它完全是一个 JSON 模板,实际上:我不想从这个动作中渲染 HTML。
  • 这个答案有点难看,因为它仍然在 render 调用中指定完整路径,这似乎没有必要。我的模板文件不是部分的,并且在浏览器中肯定会将其呈现为 templatefile,但 RSpec 测试得到一个空的 JSON 响应。
  • 您是否尝试删除模板末尾的 .erb?我知道这听起来很奇怪,但我相信您不需要它,它会影响 RSpec 测试,因为您有一个“内部带有 json 的 html”,它可能无法与 JSON.parse 一起正常工作
【解决方案2】:

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

感谢遇到同样问题的this guyhis 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-24
    • 1970-01-01
    • 2014-12-20
    • 1970-01-01
    • 2013-11-19
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多