-
Notifications
You must be signed in to change notification settings - Fork 6
Documentation & Examples
Sections
- Basic object with attributes
- Collections
- "Empty" objects
- Implicit object
- Dynamic attributes
- Deep object hierarches
- Attribute aliases
- Local Variables
- Instance Variables
- Templates
- Custom Handlers
Bldr has two top-level DSL methods -- object
and collection
. Inside a object
or collection
block, the attribute
and attributes
methods are how you build your json documents.
get '/post/:id' do
bldr :show, :locals => {:post => Post.find(params['id']) }
end
# show.bldr
object :post => post do
attributes :title, :body
end
# output
{ "post": {"title": "my title", "body": "..."} }
get '/posts' do
bldr :'posts/index.bldr', :locals => {:posts => Post.all}
end
# index.bldr
collection :posts => posts do
attributes :body, :email
end
# output
{"posts": [{"body": "epic trollery", "email": "troll@trolling.edu"}]}
If you need to build a json document whose structure doesn't rely on an object, you can do that too by not passing any args to the object
method.
object do
attribute :url, "http://zaarly.com"
attribute :success, true
end
# output
{"url": "http://zaarly.com", "success": true}
If your locals keys are the same as how you want them named in the generated JSON, you can save a few keystrokes by taking advantage of Bldr's implicit object syntax. This works for both object
and collection
.
get '/post/:id' do
bldr :show, :locals => { :post => Post.find(params['id']) }
end
# index.bldr
object :post do
attributes :id, :body, :title
end
# output
{"post": {"id": 1, "body": "...", "title": "}}
The attribute
method supports a block syntax. The block takes a single argument, which is the object currently being operated on.
object :post => post do
attribute :comment_count do |post|
post.comments.count
end
end
# output
{ "post": {"comment_count": 1} }
Bldr supports building arbitrarily deep object hierarchies. This is supported by both the object
and collection
methods.
get '/post/:id' do
bldr :show, :locals => { :post => Post.find(params['id']) }
end
# show.bldr
object :post do |post|
attributes :title
object :author do
attributes :name, :email
end
end
# output
{ "post": {"title": "my title", "author": {"name": "John", "email": "john@doe.com"}} }
When nesting collections within each other, access individual items in a collection block by passing a block variable to the collection, as you would with any other enumberable method.
get '/posts' do
bldr :index, :locals => { :posts => Post.all }
end
# index.bldr
collection :posts => posts do |post|
attributes :title
collection :comments => post.comments do |comment|
attribute(:author) { comment.author.display_name }
attribute :body
end
end
# output
{"posts": [
{ "title": "my title",
"comments": [
{"body": "...", "author": "Comment Troll"},
{"body": "...", "author": "Uber Troll"}
]
}
]}
The attribute
method allows aliasing attributes via a simple hash syntax. The key is the name of the aliased key you want to appear in the json document, and the value is the name of the object's method.
object :post => post do
attributes :title, :body
object :author => post.author do
attribute :surname => :last_name
end
end
# output
{ "post": {"title": "my title", "body": "...", "author": {"surname": "Doe"}} }
Local variables are passed from sinatra actions to bldr templates by passing the bldr
method a :locals
hash.
get '/posts' do
posts = Post.all
bldr :'posts/index.json', :locals => {:posts => posts}
end
You can access instance variables set in your controller actions in your bldr templates:
get "/posts/:id" do
@post = Post.find(params[:id])
bldr :'posts/show.bldr'
end
# posts/show.bldr
object :post => @post do
attributes :body, :title
attribute(:comment_count) { @post.comments.count }
end
The template
method includes another template/partial into the current doc. When using Sinatra, the Sinatra.settings.view
is used to determine default view path. This is usually app/views
.
# Main view
object :post => post do
attributes :title, :body
template 'user', :locals => {:user => post.author}
end
# user view
object :user => user do
attribute :name
end
# output
{ "post": {"title": "my title", "body": "...", "user": {"name": "John Doe"}} }
Bldr supports the definition of custom handlers, based on the class of specific values in the result. You would make use of this to define how specific classes are rendered by Bldr at a global level.
For example, the BSON::ObjectId
class defines to_json
and as_json
methods that produce a result like the following: {"$oid": "4e77a682364141ecf5000002"}
. If you wanted to over-ride this default format, you could do so by defining a custom handler:
# place in a file that get's loaded before your application code
Bldr.handler BSON::ObjectId do |val|
val.to_s # => "4e77a682364141ecf5000002"
end