使用Jbuilder(或其他)Rails JSON API布局

Mik*_*keL 9 layout json ruby-on-rails jbuilder

在我的rails 3.2应用程序中,我使用jbuilder来呈现来自我的JSON api的响应.

我想为所有API响应提供一个通用结构,并且布局可能是保持我的视图DRY的可能解决方案.

例如:我希望每个回复都是以下形式:

{
  status: "ok|error|redirect",
  data:   { ... JSON specific to the current view ... },
  errors: [ ... ],
  notes:  [ ... ]
}
Run Code Online (Sandbox Code Playgroud)

(其中数据的值是视图提供的json结构,其他所有内容都来自布局)

但是:我无法正确地让jbuilder布局屈服于视图.

# in layout 
json.data yield

# in view
json.some "value"
Run Code Online (Sandbox Code Playgroud)

结果是:

{"data":"{\"some\":\"value\"}"}  # arg! my json has become a string
Run Code Online (Sandbox Code Playgroud)

以另一种方式尝试:

# in layout 
yield

# in view
json.data do |json|
  json.some "value"
end
Run Code Online (Sandbox Code Playgroud)

结果是 :

{}
Run Code Online (Sandbox Code Playgroud)

有没有人用jbuilder或其他json模板gem /方法做到这一点?

这个juilder github问题表明这是可能的,但表明其他人也有类似的问题.

我看到rabl(https://github.com/nesquena/rabl/)应该支持布局(https://github.com/nesquena/rabl/wiki/Using-Layouts),但我决定不使用由于其他原因(rabl使复杂的json结构成为一场噩梦,特别是在试图控制对象根等时).

sor*_*ens 12

我会根据我们提出的解决方案为您提供替代方案:

# app/helpers/application_helper.rb
module ApplicationHelper
    def envelope(json, status, errors, notes)
        json.status status
        json.data do
            yield if block_given?
        end
        json.errors errors
        json.notes notes
    end
end
Run Code Online (Sandbox Code Playgroud)

然后,在视图中,您可以调用信封并包含您的json代码,如:

# app/views/api/v1/test/show.json.jbuilder
envelope(json, "OK" ) do
  json.some 'value'
end
Run Code Online (Sandbox Code Playgroud)


Dob*_*hev 10

你可以通过这种方式做到这一点

# api.v1.json.jbuilder - layout
json.request do
  json.message "your message"
  json.status 200
end
json.data JSON.parse(yield)

# show.json.jbuilder - action view
json.name 'Some item name'
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢你这样做的地方,但解析 JSON 只是为了再次吐出它似乎有点浪费 (2认同)

Chr*_*ell 5

迟到的答案,但帮助我得到了我想要的...

成功结果:

{ "something": {"id": 42, "message": "hello"}, "status": "ok", "errors": [] }
Run Code Online (Sandbox Code Playgroud)

错误结果:

{ "something": null, "status": "error", "errors": ["could not do the thing"] }
Run Code Online (Sandbox Code Playgroud)

码:

应用程序/控制器/ API/V1/base_controller.rb

class Api::V1::BaseController < ActionController::API
  layout 'api/v1/application'
  before_action :setup_layout_elements

  def setup_layout_elements
    @status = :ok
    @errors = []
  end

  def error!(message)
    @status = :error
    @errors << message
    nil
  end
end
Run Code Online (Sandbox Code Playgroud)

应用程序/控制器/ API/V1/some_controller.rb

class Api::V1::SomeController < Api::V1::BaseController
  def index
    @something = begin
                   possibly_error_causing_code
                 rescue
                   error!('could not do the thing')
                 end
    render builder: 'api/v1/something/index'
  end
end
Run Code Online (Sandbox Code Playgroud)

应用程序/视图/布局/ API/V1/application.json.jbuilder

json.merge!   JSON.parse(yield)
json.status   @status
json.errors   @errors
Run Code Online (Sandbox Code Playgroud)

应用程序/视图/ API/V1 /事/ index.json.jbuilder

json.something do
  json.id      @something.id
  json.message @something.to_s
end
Run Code Online (Sandbox Code Playgroud)