GraphQL + Rails na prática – Mutations

Nos posts anteriores vimos como podemos expor dados de maneira bem simples e flexível com GraphQL, agora vamos ver como podemos criar e modificar dados seguindo a mesma ideia de grafos.

Criando novos jogos

Se voltarmos no arquivo que define o nó inicial do nosso grafo (‘app/graphql/graphql_games_schema.rb’) vamos ver que tem o código que define ‘query(Types::QueryType)’, onde fizemos as últimas mudanças, e também define ‘mutation(Types::MutationType)’:

# app/graphql/types/query_type.rb
GraphqlGamesSchema = GraphQL::Schema.define do
  mutation(Types::MutationType)
  query(Types::QueryType)
end

Mutations são campos que modificam os dados dos nossos recursos, não existe uma diferença prática a ideia é mais separar conceitualmente as consultas que produzem efeitos colaterais (como atualizar, criar ou remover informações).

Vamos criar uma mutação no arquivo ‘app/graphql/types/mutation_type.rb’ que foi gerado quando instalamos GraphQL na nossa aplicação. O código é bem parecido com os outros, criamos os campos, definimos argumentos e o código do ‘resolve’ vai executar nossa lógica.

# app/graphql/types/mutation_type.rb

Types::MutationType = GraphQL::ObjectType.define do
  field :new_game do
    description 'Creates a new game'
    type Types::GameType
    argument :name, !types.String
    argument :launch_year, !types.String
    argument :description, types.String

    resolve -> (root, args, _ctx) do
      Game.create(name: args[:name],
                  launch_year: args[:launch_year],
                  description: args[:description])
    end
  end
end

Lembre que quando definimos o ‘GameType’ os campos ‘name’ e ‘launch_year’ eram obrigatórios, então precisamos também sinalizar esses atributos com o ‘!types’.

Podemos executar essa consulta no GraphiQL App da seguinte maneira:

mutation CreateGame {
  new_game(name: "The Legend of Zelda", launch_year: "1986") {
    name
    launch_year
    description
  }
}

Ao criarmos um novo jogo executamos a query da mesma forma como em qualquer outro campo. A consulta anterior vai criar um novo jogo e retornar o nome, ano de lançamento e a descrição.

Adicionando personagens aos jogos

Não adicionamos o campo para as personagens do jogo pois os o ‘GameType’ não pode ser utilizado para inputs via argumentos. Por padrão apenas os tipos escalares podem ser argumentos, vamos ver como criar input types no próximo post.

Uma maneira de contornar o problema é passar os ids das personagens que devem ser adicionadas. Vamos criar um nova mutation que busca um jogo e adiciona personagens a esse jogo:

# app/graphql/types/mutation_type.rb
field :add_char_to_game do
  description 'Adds a character to a game'
  type Types::GameType
  argument :game_id, !types.Int
  argument :characters_id, !types[types.Int]

  resolve -> (root, args, _ctx) do
    game = Game.find(args[:game_id])
    args[:characters_id].each do |id|
      char = Character.find(id)
      game.characters << char unless game.characters.include?(char)
    end
    game.save
    game
  end
end

No 'resolve' desse campo vamos adicionar cada um dos ids passados no 'args[:characters_id]' e adicionar a personagem ao jogo caso já não esteja lá. No final salvamos e retornamos o jogo.

Podemos usar essa consulta pra adicionar personagens aos jogos:

mutation AddCharToGame {
  add_char_to_game(game_id: 2, characters_id: [4]) {
    name
    characters {
      name
    }
  }
}

Seguindo a mesma ideia podemos criar um mutation que remove jogo, basta passar o id do jogo e no 'resolve' remover aquela entrada. Com isso, conseguimos seguir todo o fluxo de CRUD (Create, Read, Update e Delete) com o GraphQL.

No entanto o nosso exemplo está bem simples, não lidamos com erros e nem imprevistos, além disso toda a lógica da aplicação vive nos resolvers dos campos. Assim provavelmente vai ser complicado testar esse código e por consequência evoluí-lo. Se você quer saber mais como podemos fazer essa separação acompanha os próximos posts e compartilha essa série de tutoriais com as pessoas que você acha que gostariam de aprender mais sobre GraphQL!

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