jbuilder

Jbuilder: generate JSON objects with a Builder-style DSL

  • 所有者: rails/jbuilder
  • 平台:
  • 許可證: MIT License
  • 分類:
  • 主題:
  • 喜歡:
    0
      比較:

Github星跟蹤圖

Jbuilder

Jbuilder gives you a simple DSL for declaring JSON structures that beats
manipulating giant hash structures. This is particularly helpful when the
generation process is fraught with conditionals and loops. Here's a simple
example:

# app/views/messages/show.json.jbuilder

json.content format_content(@message.content)
json.(@message, :created_at, :updated_at)

json.author do
  json.name @message.creator.name.familiar
  json.email_address @message.creator.email_address_with_name
  json.url url_for(@message.creator, format: :json)
end

if current_user.admin?
  json.visitors calculate_visitors(@message)
end

json.comments @message.comments, :content, :created_at

json.attachments @message.attachments do, attachment, json.filename attachment.filename
  json.url url_for(attachment)
end

This will build the following structure:

{
  "content": "<p>This is <i>serious</i> monkey business</p>",
  "created_at": "2011-10-29T20:45:28-05:00",
  "updated_at": "2011-10-29T20:45:28-05:00",

  "author": {
    "name": "David H.",
    "email_address": "'David Heinemeier Hansson' <david@heinemeierhansson.com>",
    "url": "http://example.com/users/1-david.json"
  },

  "visitors": 15,

  "comments": [
    { "content": "Hello everyone!", "created_at": "2011-10-29T20:45:28-05:00" },
    { "content": "To you my good sir!", "created_at": "2011-10-29T20:47:28-05:00" }
  ],

  "attachments": [
    { "filename": "forecast.xls", "url": "http://example.com/downloads/forecast.xls" },
    { "filename": "presentation.pdf", "url": "http://example.com/downloads/presentation.pdf" }
  ]
}

To define attribute and structure names dynamically, use the set! method:

json.set! :author do
  json.set! :name, 'David'
end

# => {"author": { "name": "David" }}

To merge existing hash or array to current context:

hash = { author: { name: "David" } }
json.post do
  json.title "Merge HOWTO"
  json.merge! hash
end

# => "post": { "title": "Merge HOWTO", "author": { "name": "David" } }

Top level arrays can be handled directly. Useful for index and other collection actions.

# @comments = @post.comments

json.array! @comments do, comment, next if comment.marked_as_spam_by?(current_user)

  json.body comment.body
  json.author do
    json.first_name comment.author.first_name
    json.last_name comment.author.last_name
  end
end

# => [ { "body": "great post...", "author": { "first_name": "Joe", "last_name": "Bloe" }} ]

You can also extract attributes from array directly.

# @people = People.all

json.array! @people, :id, :name

# => [ { "id": 1, "name": "David" }, { "id": 2, "name": "Jamie" } ]

Jbuilder objects can be directly nested inside each other. Useful for composing objects.

class Person
  # ... Class Definition ... #
  def to_builder
    Jbuilder.new do, person, person.(self, :name, :age)
    end
  end
end

class Company
  # ... Class Definition ... #
  def to_builder
    Jbuilder.new do, company, company.name name
      company.president president.to_builder
    end
  end
end

company = Company.new('Doodle Corp', Person.new('John Stobs', 58))
company.to_builder.target!

# => {"name":"Doodle Corp","president":{"name":"John Stobs","age":58}}

You can either use Jbuilder stand-alone or directly as an ActionView template
language. When required in Rails, you can create views a la show.json.jbuilder
(the json is already yielded):

# Any helpers available to views are available to the builder
json.content format_content(@message.content)
json.(@message, :created_at, :updated_at)

json.author do
  json.name @message.creator.name.familiar
  json.email_address @message.creator.email_address_with_name
  json.url url_for(@message.creator, format: :json)
end

if current_user.admin?
  json.visitors calculate_visitors(@message)
end

You can use partials as well. The following will render the file
views/comments/_comments.json.jbuilder, and set a local variable
comments with all this message's comments, which you can use inside
the partial.

json.partial! 'comments/comments', comments: @message.comments

It's also possible to render collections of partials:

json.array! @posts, partial: 'posts/post', as: :post

# or

json.partial! 'posts/post', collection: @posts, as: :post

# or

json.partial! partial: 'posts/post', collection: @posts, as: :post

# or

json.comments @post.comments, partial: 'comments/comment', as: :comment

The as: :some_symbol is used with partials. It will take care of mapping the passed in object to a variable for the partial. If the value is a collection (either implicitly or explicitly by using the collection: option, then each value of the collection is passed to the partial as the variable some_symbol. If the value is a singular object, then the object is passed to the partial as the variable some_symbol.

Be sure not to confuse the as: option to mean nesting of the partial. For example:

 # Use the default `views/comments/_comment.json.jbuilder`, putting @comment as the comment local variable.
 # Note, `comment` attributes are "inlined".
 json.partial! @comment, as: :comment

is quite different than:

 # comment attributes are nested under a "comment" property
json.comment do
  json.partial! "/comments/comment.json.jbuilder", comment: @comment
end

You can pass any objects into partial templates with or without :locals option.

json.partial! 'sub_template', locals: { user: user }

# or

json.partial! 'sub_template', user: user

You can explicitly make Jbuilder object return null if you want:

json.extract! @post, :id, :title, :content, :published_at
json.author do
  if @post.anonymous?
    json.null! # or json.nil!
  else
    json.first_name @post.author_first_name
    json.last_name @post.author_last_name
  end
end

To prevent Jbuilder from including null values in the output, you can use the ignore_nil! method:

json.ignore_nil!
json.foo nil
json.bar "bar"
# => { "bar": "bar" }

Fragment caching is supported, it uses Rails.cache and works like caching in
HTML templates:

json.cache! ['v1', @person], expires_in: 10.minutes do
  json.extract! @person, :name, :age
end

You can also conditionally cache a block by using cache_if! like this:

json.cache_if! !admin?, ['v1', @person], expires_in: 10.minutes do
  json.extract! @person, :name, :age
end

If you are rendering fragments for a collection of objects, have a look at
jbuilder_cache_multi gem. It uses fetch_multi (>= Rails 4.1) to fetch
multiple keys at once.

Keys can be auto formatted using key_format!, this can be used to convert
keynames from the standard ruby_format to camelCase:

json.key_format! camelize: :lower
json.first_name 'David'

# => { "firstName": "David" }

You can set this globally with the class method key_format (from inside your
environment.rb for example):

Jbuilder.key_format camelize: :lower

Contributing to Jbuilder

Jbuilder is the work of many contributors. You're encouraged to submit pull requests, propose
features and discuss issues.

See CONTRIBUTING.

License

Jbuilder is released under the MIT License.

主要指標

概覽
名稱與所有者rails/jbuilder
主編程語言Ruby
編程語言Ruby (語言數: 2)
平台
許可證MIT License
所有者活动
創建於2011-11-27 14:02:35
推送於2025-04-04 00:14:28
最后一次提交
發布數74
最新版本名稱v2.13.0 (發布於 )
第一版名稱v0.3.1 (發布於 )
用户参与
星數4.4k
關注者數85
派生數440
提交數790
已啟用問題?
問題數300
打開的問題數37
拉請求數188
打開的拉請求數20
關閉的拉請求數79
项目设置
已啟用Wiki?
已存檔?
是復刻?
已鎖定?
是鏡像?
是私有?