alskaa
alskaa

Reputation: 394

Rails Rabl - Custom array keys

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...

Upvotes: 2

Views: 484

Answers (1)

Leantraxxx
Leantraxxx

Reputation: 4596

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 if GET /api/games really exists but, you get the idea.
  • I'm assuming you have one position by player in one game.

Upvotes: 1

Related Questions