I'm trying to customize my RABL API response. I have a collection of games, and each game contains multiple players. For now my players are stored in an array, but I need to access them by a key so I'd like to customize my json response.
Here is my base.rabl
file:
collection @games
attributes :id
child(:players) do |a|
attributes :id, :position
end
This is what I get:
[
{
id: 1,
players: [
{
id: 27,
position: 'goalkeeper'
},
{
id: 32,
position: 'striker'
},
{
id: 45,
position: 'defender'
}
]
}
]
And this is what I'm trying to get:
[
{
id: 1,
goalkeeper: {
id: 27
},
striker: {
id: 32
},
defender: {
id: 45
}
}
]
For now I can't find a way to display the players other than in an array of objects.
Could someone give me a hit? I tried a lot of rabl configurations but without success for now...
EDIT:
I changed the attributes so it is more explicit. Each game has numerous players and each player has a different position.
In order to add more details so you could understand what I'm trying to achieve, here is my best attempt:
base.rabl file:
object @games
@games.each do |game|
node(:id) { |_| game.id }
game.players.each do |player|
if (player.position == 'goalkeeper')
node(:goalkeeper) { |_| player.id }
elsif (player.position == 'striker')
node(:striker) { |_| player.id }
end
end
end
And this is what I get:
[
{
id: 1,
goalkeeper: {
id: 27
},
striker: {
id: 32
}
},
{
id: 1,
goalkeeper: {
id: 27
},
striker: {
id: 32
}
}
]
The structure is what I want, but each game returned is the same. If my query result contains 4 games, it returns 4 games but they are all the same...
If you have the models...
class Game < ActiveRecord::Base
has_many :players
end
class Player < ActiveRecord::Base
belongs_to :game
end
In your base.json.rabl
file you can do:
attributes :id
node do |game|
game.players.each do |player|
node(player.position) { { id: player.id } } # I suggest node(pos) { player.id }
end
end
In your index.json.rabl
you need to have:
collection @games
extends 'api/games/base' # the base.rabl path
In your show.json.rabl
you need to have:
object @game
extends 'api/games/base' # the base.rabl path
In your GamesController
you need to do:
respond_to :json
def index
@games = Game.all
respond_with @games
end
def show
@game = Game.find(params[:id)
respond_with @game
end
So, if your request is to GET /api/games
you will hit index.json.rabl
and you will get your desired response.
If you want to see only one game, you need to hit GET /api/games/:id
- I'm assuming your have a namespace
api
. I don't know ifGET /api/games
really exists but, you get the idea.- I'm assuming you have one position by player in one game.