Giter Club home page Giter Club logo

graphql-workshop's Introduction

GraphQL Workshop ๐ŸŒˆ

Disclaimer: this is an almost identical copy of Adzz's ex_ample repo, but has been specially adapted to be shorter and accessible to those new to elixir and GraphQL.

The idea is to step through the branches completing the exercises outlined in the readme as you go. Answers can be found at the top of each branch's README for the preceeding section.

master
my-first-query
my-second-query
my-first-mutation
my-first-resolving-function

Background information ๐Ÿ–ผ

Note, these are NOT instructions - you don't need to do anything outlined in this section, but please read to understand the structure of the repo

Umbrella projects โ˜‚๏ธ

This repo is an 'umbrella' project. Umbrella projects are a great way to manage internal dependencies for your applications. Internal dependencies can be thought of as libraries that can sit on their own - but that you don't want to or cannot open source. They are things that you can configure their own releases for (so can be released independently from the rest of the application), but are conveniently grouped together into one git repo.

When is an umbrella project a good idea?
If you have ever had one repo rely on another, you'll soon find umbrella projects to be lifesavers; no more using git tags and bumping versions in your mix files so you can get new features!

However, apps within an umbrella projects are not completely decoupled. From the docs

While it provides a degree of separation between applications, those applications are not fully decoupled, as they are assumed to share the same configuration and the same dependencies.

And

If you find yourself in a position where you want to use different configurations in each application for the same dependency or use different dependency versions, then it is likely your codebase has grown beyond what umbrellas can provide.

Creating an umbrella project โ›ฑ

So far to create this repo, we first ran this command:

mix new ex_ample --umbrella

The name of the app is ex_ample, and the umbrella flag does exactly what you think it does.

Adding to the umbrella โ˜”๏ธ

We added new individual apps to the umbrella project by running a command like this (from the root of the project):

cd apps && mix new app_name --sup

The sup flag stands for supervision, it just tells Mix to generate a supervision tree automatically for us, instead of having to build one manually. More in the docs ๐Ÿ‘ฉโ€โš•๏ธ

We have added an app called ex_ample_backend. This will act as the datasource for our application. It has VERY limited capabilities. I don't recommend that you read the code unless you have a penchant for punishment. I certainly don't recomend you use it past this exercise.

Adding a phoenix app ๐Ÿฆœ

We have created a phoenix (web server) app called graphql using a command similar to this one:

cd apps && mix phx.new name_of_app --no-ecto --no-html

--no-ecto and --no-html flags are optional. The --no-ecto flag means Ecto files are not generated and the --no-html means no HTML views are generated (Ecto is a database wrapper for Elixir and as this example has no database, we don't need it.)

Wait, what is Phoenix?
Phoenix is a web development framework written in Elixir which implements the server-side Model View Controller (MVC) pattern. Check out the docs here: https://hexdocs.pm/phoenix/overview.html#content. Phoenix is the top layer of a multi-layer system designed to be modular and flexible. The other layers include Cowboy, Plug and Ecto.

Adding dependencies ๐Ÿน

We wanted to add 2 dependencies to this project:

What is Absinthe? Why are we adding it?
Absinthe is the GraphQL toolkit for Elixir, built to suit Elixir's capabilities and style. With Absinthe, you define the schema and resolution functions and it executes GraphQL documents.

On client side Absinthe has support for Relay and Apollo client and in Elixir it uses Plug and Phoenix to support HTTP APIs, via absinthe_plug and absinthe_phoenix packages. It also has support for Ecto via the absinthe_ecto package.

Adding dependencies in elixir doesn't work like it does in javacript (npm install jest etc) - there are no magic words to install! We have added 2 dependencies manually in the mix.exs file inside the graphql app:

{:absinthe, "~> 1.4.0"},
{:absinthe_plug, "~> 1.4.0"},

So the dependency section now looks like this:

...
  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [
      {:phoenix, "~> 1.3.3"},
      {:phoenix_pubsub, "~> 1.0"},
      {:gettext, "~> 0.11"},
      {:cowboy, "~> 1.0"},
      {:absinthe, "~> 1.4.0"},
      {:absinthe_plug, "~> 1.4.0"},
      {:jason, "~> 1.1"},
      {:ex_ample_backend, in_umbrella: true},
      {:cors_plug, "~> 1.5"}
    ]
  end
end

Adding web server routes ๐Ÿ—บ

Inside our router.ex file in the graphql app, we've added 2 new routes. One is the route that Absinthe and Graphql use to host our GraphQL api (/graphql), the other is the route that the Graphiql tool uses (/graphiql), which is only available in development.

  scope "/graphql" do
      forward(
        "/",
        Absinthe.Plug,
        schema: Graphql.Schema,
        json_codec: Jason
      )
    end

  if Mix.env() == :dev do
    forward(
      "/graphiql",
      Absinthe.Plug.GraphiQL,
      schema: Graphql.Schema,
      json_codec: Jason,
      default_url: "/graphiql",
      interface: :advanced
    )
  end

You don't need to worry too much about the syntax here, or remember it, its just for information!

Adding a schema file and some smoke tests ๐Ÿ’จ

We have added a schema.ex file and add a resolvers folder with a resolver.ex file in it.

Inside schema.ex we have defined the schema module, imported Absinthe, and written two 'hello world' smoke tests so we can check our api and resolvers are all working.

defmodule Graphql.Schema do
  # This allows us to use the absinthe schema notation like 'query' and 'field'
  use Absinthe.Schema

  query do
    field :is_this_thing_on, type: :string do
      resolve(&Graphql.Resolver.smoke_test/2)
    end
  end

  mutation do
    field :echo_text, type: :string do
      arg(:input, :string)
      resolve(&Graphql.Resolver.test_update/2)
    end
  end
end

Inside resolvers.ex we added the two resolver functions from the schema.

defmodule Graphql.Resolver do
  def smoke_test(_args, _info) do
    {:ok, "Yes!"}
  end

  def test_update(%{input: input}, _info) do
    {:ok, input}
  end
end

Try and understand what's happening in these two files, as you will be using the same syntax and concepts to write your own queries shortly! Speak to your partner or a workshop leader if you have questions.

Side point: note how the Absinthe resolve function (in the schema) expects resolver functions to return an "ok tuple" (or an "error tuple" in the case of an error), which is a tuple containing an ok or error atom and some data. This is a common way in elixir to handle error catching and propagation.

# ok tuple (response is a variable that would contain some data)
{:ok, reponse}

# error tuple
{:error, response}

Workshop Instructions

  1. Clone this repo:
git clone https://github.com/developess/GraphQL-Workshop
  1. Install Phoenix web framework if you don't have it already. You can find instructions here:

  2. Fetch the dependencies for the repo by running: mix deps.get

  3. Get your Phoenix server running: mix phx.server

If you go to localhost:4000/graphiql you should be able to see the Graphiql interface with the smoke tests above in the docs panel! Try writing a query or mutation that calls one of the smoke tests.

Then, checkout the next branch: my-first-query for your first challenge.

graphql-workshop's People

Contributors

adzz avatar developess avatar kekko1212 avatar onekelvinsmith avatar glazy avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.