jckly
jckly

Reputation: 851

Returning 2 collections in RABL?

I'm trying to return 2 collections in RABL. But I'm having some trouble. What happens is it only returns the second collection when I run it.

Here is the function for the index page the rabl is rendering:

def index
   @friends = @currentuser.friends
   @pendingfriends = @currentuser.pending_friends
end

In my RABL page I am trying to return both collections like so:

collection @friends, :root => "friends", :object_root => "user"
attributes :id, :username

collection @pendingfriends, :root => "pendingfriends", :object_root => "user"
attributes :id, :username

What happens is it only renders the second collection "pending friends":

{
    "pendingfriends": [
        {
            "user": {
                "id": 3,
                "username": "ken"
            }
        }
    ]
}

If I delete the second collection though the first one appears fine. I'm wondering whats the correct way I can render the 2 collections in my RABL template.

Thanks for any help.

Upvotes: 2

Views: 514

Answers (1)

blotto
blotto

Reputation: 3407

Based on your code looks like you want user as the document root. Then create two child nodes, one for each collection. basically 'gluing' the collections to the user. Since they are basically the same Model, you'll need to alias the collections by using nodes for each collection. Using partials to keep it DRY.

 @user = @currentuser # for example below

file : users/user.rabl

 object @user
 extends "users/base"

 node :friends do |u|
  partial("users/friends", :object => u.friends) # :object => @friends)
 end

 node :pendingfriends do |u|
  partial("users/friends", :object => u.pending_friends) # @pendingfriends)
 end

file : users/base.rabl

 attributes :id, :name

file : users/friends.rabl

collection @nil , :object_root => false
extends "users/base"

The one thing I dont link about this is the collection object @nil (used to express a point) is ignored since in user.rabl the object is explicitly set. Which works for this case, but prevents calling friends.rabl directly. So if you wish to also call this file directly, set to a global collection you intend to use... like @users. Then you can call collection.rabl directly in your controller if you wish and not just as a partial. Then...

file : users/friends.rabl

collection @users , :object_root => false
extends "users/base"

this would give you a structure of

 {
     "user": {
         "id": "hello",
         "name": "me",
         "friends": [
             {
                 "id": "hello",
                 "name": "me2"
             }
         ],
         "pendingfriends": [
             {
                 "id": "hello",
                 "name": "me3"
             }
         ]
     }
 }

This gives further benefit as now you can build a collection for users ( and their friends ) as such

file : users/users.rabl

 collection @users , :object_root => false
 extends 'users/user'

Upvotes: 1

Related Questions