Upgrade to Pro — share decks privately, control downloads, hide ads and more …

No REST for the Wicked

Ben Wilson
September 01, 2016

No REST for the Wicked

Build a GraphQL API with http://absinthe-graphql.org/

Ben Wilson

September 01, 2016
Tweet

Other Decks in Programming

Transcript

  1. the Wicked
    for
    No REST
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  2. CARGOSENSE

    View Slide

  3. The BEAM
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    some reasons to like

    View Slide

  4. REST
    GET /users/1
    {
    name: "Joe Bob"
    email: "[email protected]"
    friends: [
    "/users/5",
    "/users/7",
    "/users/9",
    ],
    organization_id: 1
    }
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  5. View Slide

  6. REST, Camp 2
    GET /users/1
    {
    name: "Joe Bob”,
    organization_id: 1,
    friends: [
    {
    name: "Fred Jones",
    organization: {
    name: "Cool Folks LLC",
    payment_plan_id: 5
    }
    },

    }
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  7. View Slide

  8. {
    name: "Joe Bob”
    organization_id: 1,
    friends: [
    {
    name: "Fred Jones",
    organization: {
    name: "Cool Folks LLC",
    payment_plan_id: 5
    }
    },

    ]
    }
    GET /users/1
    REST, Camp 2
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  9. GraphQL
    Declarative & Hierarchical
    Strongly Typed
    Concurrent
    Application-Focused
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    some reasons to like

    View Slide

  10. Declarative
    &
    Hierarchical
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    it’s

    View Slide

  11. GraphQL
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    {
    user: {
    name: "Joe Bob",
    email: "[email protected]",
    friends: [
    {name: "Fred Jones"},
    {name: "Jane Smith"},
    {name: "Rebecca Jones"},
    ...
    ]
    }
    }
    {
    user(id: 1) {
    name
    email
    friends {
    name
    }
    }
    }

    View Slide

  12. http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    Strongly
    Typed
    it’s

    View Slide

  13. Directive
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    List
    Interface
    Enum
    Union
    Scalar
    Object
    NonNull

    View Slide

  14. GET /events?date=2016-08-30&location_id=4
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    @valid_filters ~w(date location_id name)a
    def index(conn, params) do
    filters =
    @valid_filters
    |> Enum.reduce(%{}, fn key, filters ->
    case Map.fetch(params, Atom.to_string(key)) do
    {:ok, value} ->
    add_filter(key, value, filters)
    _ ->
    query
    end
    end)
    render("index.json", events: Event.list(filters))
    end

    View Slide

  15. But wait! there’s more…
    def add_filter(:date, date, filters) do
    case Calendar.parse(date) do
    {:ok, date} ->
    Map.put(filters, :date, date)
    _ ->
    filters
    end
    end
    def add_filter(key, value, filters) do
    Map.put(filters, key, value)
    end

    View Slide

  16. GET /events?date=2016-08-30&location_id=4
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    @valid_filters ~w(date location_id name)a
    def index(conn, params) do
    filters =
    @valid_filters
    |> Enum.reduce(%{}, fn key, filters ->
    case Map.fetch(params, Atom.to_string(key)) do
    {:ok, value} ->
    add_filter(key, value, filters)
    _ ->
    query
    end
    end)
    render("index.json", events: Event.list(filters))
    end

    View Slide

  17. {
    events(location_id: 4, date: "2016-08-30") {
    name
    }
    }
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    Using:
    def events(filters, _) do
    {:ok, Event.list(filters)}
    end

    View Slide

  18. {
    events(location_id: 4, date: "2016-08-30") {
    name
    }
    }
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    def events(filters, _) do
    ...
    end
    field :events, list_of(:event) do
    arg :date, :date
    arg :location_id, :id
    arg :name, :string
    resolve &events/2
    end

    View Slide

  19. http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    Custom Scalar
    @desc """
    ISO Date
    2015-11-21
    2015-01-02
    """
    scalar :date do
    parse &Calendar.Date.Parse.iso8601/1
    serialize &Calendar.Date.Format.iso8601/1
    end

    View Slide

  20. http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    Built-in Scalar
    @desc """
    The `String` scalar type represents textual
    data, represented as UTF-8 character sequences.
    ...
    """
    scalar :string do
    serialize &to_string/1
    parse &parse_string/1
    end

    View Slide

  21. http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    @desc """
    A planned occasion, like a meeting
    or conference
    """
    object :event do
    @desc "The date on which the event occurs"
    field :date, non_null(:date)
    @desc "The location at which the event happens"
    field :location, non_null(:location)
    @desc "The name of the event"
    field :name, non_null(:string)
    field :attendees, list_of(:person)
    end

    View Slide

  22. Introspection
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    {
    __schema {
    types {
    name
    description
    }
    }
    }
    {
    __schema: {
    types: [
    {
    name: "Event",
    description: "A planned …"
    },
    {
    name: "Person",
    description: "Someone …"
    },
    ...
    ]
    }
    }

    View Slide

  23. GraphiQL
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    https://github.com/graphql/graphiql

    View Slide

  24. {
    user: {
    name: "Bob",
    primaryOrganization: {
    id: 7,
    name: "Elixir Co INC"
    }
    },
    location: {
    name: "Headquarters",
    organization: {
    id: 7,
    name: "Elixir Co INC"
    }
    }
    }
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  25. Directives
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    {
    feed: {
    stories: [
    {
    author: {
    name: "Ben Wilson"
    },
    message: "Elixir Rocks!"
    },
    {
    author: {
    name: "Bruce Williams"
    },
    message: "GraphQL is the bomb!"
    },
    ...
    ]
    }
    }
    {
    feed {
    stories {
    author {
    name
    }
    comments @defer {
    author {
    name
    }
    }
    message
    }
    }
    }

    View Slide

  26. Deferred Content
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    {
    path: ["feed", "stories", 0, "comments"],
    data: [
    {
    author: {
    name: "Joe Bob",
    message: "Commenting is fun"
    }
    },
    ...
    ]
    }

    View Slide

  27. Directives
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    {
    feed {
    stories @stream {
    author {
    name
    }
    comments @defer {
    author {
    name
    }
    }
    message
    }
    }
    }
    {
    feed {
    stories @live {
    author {
    name
    }
    comments @defer {
    author {
    name
    }
    }
    message
    }
    }
    }
    {
    feed {
    stories {
    author {
    name
    }
    comments @defer {
    author {
    name
    }
    }
    message
    }
    }
    }

    View Slide

  28. Absinthe Goals
    Correct
    Easy to Use
    Idiomatic
    Performant
    Community Oriented
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  29. Schema Errors
    web/schema.ex:12: Users :usre is not defined in your schema.
    Types must exist if referenced.
    object :organization do
    field :name, :string
    field :users, list_of(:usre)
    end
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  30. Schema Compilation
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    @desc "A faction in the Star Wars saga"
    node object :faction do
    @desc "The name of the faction"
    field :name, :string
    @desc "The ships used by the faction."
    connection field :ships, node_type: :ship do
    resolve &Ship.list/2
    end
    end

    View Slide

  31. Absinthe v1.2

    View Slide

  32. ?
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    {
    user: {
    name: "Joe Bob",
    email: "[email protected]",
    friends: [
    {name: "Fred Jones"},
    {name: "Jane Smith"},
    {name: "Rebecca Jones"},
    ...
    ]
    }
    }
    {
    user(id: 1) {
    name
    email
    friends {
    name
    }
    }
    }

    View Slide

  33. Absinthe vNext
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  34. Query Compilation
    ~A"""

    query Fast($id: ID){
    performanceCritical(id: $id) {
    stuff
    things {
    name
    }
    }
    }
    """
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512

    View Slide

  35. Projection
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    def events(filters, _) do
    {:ok Event.list(filters)}
    end
    def list(filters) do
    Event
    |> where(^filters)
    |> Repo.all
    end

    View Slide

  36. Projection
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    def events(filters, graphql_info) do
    preloads = Absinthe.Ecto.preloads(graphql_info)
    selections = Absinthe.Ecto.preloads(graphql_info)
    {:ok Event.list(filters, preloads, selections)}
    end
    def list(filters, preloads, selections) do
    Event
    |> where(^filters)
    |> select(^selections)
    |> preload(^preloads)
    |> Repo.all
    end

    View Slide

  37. Real Time Data
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    {
    feed {
    stories @live {
    author {
    name
    }
    comments @defer {
    author {
    name
    }
    }
    message
    }
    }
    }
    subscription {
    stories(author_id: 1) {
    message
    author {
    name
    }
    }
    }

    View Slide

  38. Questions?
    http://absinthe-graphql.org
    Ben Wilson
    @benwilson512
    Background image green by Ana C., license available here.

    View Slide