GraphQL + Rails na prática – Models e Types

No post anterior vimos como configurar uma aplicação Rails API para expor um endpoint GraphQL. Agora vamos entender como podemos expor objetos modelos de maneira fácil via GraphQL.

Criando modelos

Como vamos expor informações sobre jogos e seus personagens, vamos começar criando um modelo Game que vai conter o nome, descrição e o ano que o jogo surgiu.

bundle exec rails generate model Game name:string description:text launch_year:string

O próximo passo é criar um modelo para representar os personagens, vamos guardar apenas o nome do personagem por enquanto.

bundle exec rails generate model Character name:string

Agora precisamos criar uma relação entre Game e Character, já que um jogo possui muitas personagens e uma personagem pode aparecer em vários jogos. Vamos criar uma tabela de associação chamada para mapear os ids dos jogos e os ids das personagens.

bundle exec rails generate model Project game:references character:references

Agora basta adicionar as relações entre games e characters através dos projetos:

# app/models/game.rb
class Game < ApplicationRecord
 has_many :projects
 has_many :characters, through: :projects
end

# app/models/character.rb

class Character < ApplicationRecord
 has_many :projects
 has_many :games, through: :projects
end

O último passo é popular os modelos com alguns dados de exemplo utilizando o arquivo 'db/seeds.rb'. Coloque o seguinte código no arquivos e devemos estar prontos pra começar:

# db/seeds.rb
# personagens
mario = Character.create(name: "Mario")
peach = Character.create(name: "Peach")
dk = Character.create(name: "Donkey Kong")
zelda = Character.create(name: "Zelda")

# games
mario_world = Game.create(name: "Super Mario World", description: "SNES game", launch_year: "1990", characters: [mario, peach])
mario_kart = Game.create(name: "Mario Kart 8", description: "Wii U Game", launch_year: "2014", characters: [mario, peach, dk])
smash_bros = Game.create(name: "Super Smash Bros Wii U", description: "Wii U Game", launch_year: "2014", characters: [mario, peach, dk, zelda])
# adicionando games aos personagens
mario.games << [mario_world, mario_kart, smash_bros]
mario.save

peach.games << [mario_world, mario_kart, smash_bros]
peach.save

zelda.games << [smash_bros]
zelda.save

dk.games << [mario_kart, smash_bros]
dk.save

Agora é só rodar as migrações e criar os dados de exemplo

bundle exec rails db:create db:migrate db:seed

Criando tipos GraphQL

Crie um arquivo novo dentro de ‘app/graphql/types/’ chamado ‘game_type’ e nele vamos criar o novo tipo (bem semelhante ao que já está definido em ‘query_type.rb’). Vamos criar uma constante ‘Types::GameType’ que ira guardar o novo tipo:

# app/graphql/types/game_type.rb
Types::GameType = GraphQL::ObjectType.define do
end

Agora vamos criar os campos que serão expostos via GraphQL e definir seus tipos. Como vamos expor exatamente os mesmos atributos dos modelos (com os mesmos nomes), não é necessário criar um ‘resolve’ para cada campo, basta definir o campo e seu tipo:

# app/graphql/types/game_type.rb
Types::GameType = GraphQL::ObjectType.define do
  field :name, !types.String
  field :description, types.String
  field :launch_year, !types.String
end

Criando um consulta

Agora, para conseguirmos expor os dados de um jogo precisamos criar um query que retorne esse query type. Vamos na query raiz em ‘app/graphql/types/query_type.rb’ e lá criaremos uma consulta onde, dado um id, será retornado um GameType.

# app/graphql/types/query_type.rb
Types::QueryType = GraphQL::ObjectType.define do
  field :game do
    type Types::GameType
    argument :id, !types.Int
    resolve -> (root, args, ctx) {
      Game.find(args[:id])
    }
  end
end

Essa definição de query tem algumas diferenças, o ‘type’ é aquela constante que criamos ‘Types::GameType’, também existe um ‘argument’ chamado ‘:id’ e do tipo ‘types.Int’ (a exclamação indica que é um argumento obrigatório). No ‘resolve’ passamos um bloco com alguns argumentos (não importantes por hora) e fazemos a busca pelo id do ‘Game’.

Agora se abrirmos o GraphQL App de novo apontando para http://localhost:3000/graphql poderemos executar a seguinte consulta:

query {
  game(id: 1) {
    name
    description
    launch_year
  }
}

Screen Shot 2018-02-18 at 11.32.57

O legal das consultas com GraphQL é que elas dão uma flexibilidade bem legal para quem consome a API, podemos escolher exatamente quais dados queremos receber e teremos apenas eles na resposta.

Seguindo uma ideia parecida podemos criar um tipo para representar uma personagem e uma query para expô-la. Criar uma consulta para cada tipo funciona de maneira similar ao REST mas para entender o que faz GraphQL ser tão legal precisamos pensar em grafos! Se você curtiu conhecer mais sobre GraphQL avisa lá no twitter e fica ligado nos próximos posts!

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s