Display custom links above top level arrays using Jbuilder #110

Closed
boddhisattva opened this Issue Mar 14, 2013 · 9 comments

Projects

None yet

2 participants

@boddhisattva

I have a custom JSON response in which I display a collection of 15 posts along with related data like comments etc., as part of an API call. I am displaying the entire collection using Jbuilder .

json.array!(@posts) do |post|
..
..
end
I want to display pagination links above the json response of the 15 posts, in order to get the next set of posts with the appropriate next set of next page and prev page pagination links. In my abc.json.jbuilder file if I try doing it as per the below code, I don't get links to the next and prev page as part of my json response.

json.pagination_links do
json.set!(:next_page_link,"#{@next_page_link}")

json.set!(:prev_page_link,"#{@prev_page_link}")

end

json.array!(@posts) do |post|
..
..
end
The only response, that I get is the array which has a collection of posts. Which looks like below:-

[
-{post1}
-{post2}
-..
]
I guess there is something that I might be missing. Can anybody please suggest me any work arounds?

Thanks.

@rwz

You can't combine unnested array with other properties because JSON itself doesn't support it.

You either get an array of posts, or an object with pagination data and posts, which might looks like this:

post_klass = Struct.new(:id, :content)
@posts = 10.times{ |i| post_klass.new(i+1, "post ##{i+1}") }

Jbuilder.encode do |json|
  json.pagination do
    json.prev_link 'http://previous.link'
    json.next_link 'http://next.link'
  end

  json.posts @posts, :id, :content
end

Which will output following JSON:

{
  "pagination": {
    "prev_link": "http://previous.link",
    "next_link": "http://next.link"
  },
  "posts": [
    { "id": 1, "content": "post #1" },
    { "id": 2, "content": "post #2" },
    ...
  ]
}
@rwz rwz closed this Mar 14, 2013
@rwz

It might me a good idea to add some kind of warning when you try to turn non-empty set into unnested array with potential data-loss.

@boddhisattva

@rwz I am able to use RABL to display the below structure:-


{

    "next_page_link": "http://",
    "prev_page_link": "http://",
    "posts": [ … ]

}

Since I am able to generate this in RABL, I was thinking this has nothing to do with JSON support. Is there no way I can do the same with Jbuilder ?

Also just one more thing, does JBuilder come with a default JSON Engine(like yajl or oj) ? If not, can we use a JSON Engine that might help parse the JSON faster, thereby reducing the response time to generate the JSON data ?

@rwz

1) The structure you've mentioned is not an array. It is an object with an array attribute. You've said you wanted an array with fields, which is impossible in JSON. You can do the same structure with Jbuilder with this straightforward code:

json.next_page_link @next_page_link
json.prev_page_link @prev_page_link
json.posts @posts do |post|
  # here goes post stuff
end

2) Jbuilder uses MultiJson internally which allows you to use pretty much any json engine you want.

@boddhisattva

@rwz I might have been wrong by specifying the way I wanted the array or the entire json structure. My bad. But, this is actually just what I wanted. Thank you very much .

It would be really nice I guess, if the Readme could be just updated with this one line of code, specifying how alternatively one can use collections with Jbuilder.

I was looking at where to specify the JSON Engine for Multi JSON, I came across this Stackoverflow link. Is there any place at a global level(within my app) where I can specify the json engine to be used when using Jbuilder ?

Can I specify them in any initializers for instance ? Where does one generally specify their custom JSON engine when one makes use of Jbuilder ?

@rwz

Jbuilder uses global MultiJson adapter. There is not way currently to tell Jbuilder use specified non system-wide adapter.

@boddhisattva

So there is no way I can configure different JSON Engines inspite of Jbuilder using MultiJson? Do you know which is the default JSON Engine that Multijson uses ? If the need be, can I override the global MutliJson adapter by specifying a JSON engine in my controller after requiring 'multi_json' in the same ?

@rwz

Read MultiJson docs, it's all there. Also, in recent versions of MultiJson you can specify adapter for a block, which makes it possible to use an adapter in around_filter for controller. And since jbuilder is getting invoked in the view layer, you can override adapter jbuilder uses like that.

@boddhisattva

@rwz Thanks.. will give it a try..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment