Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a908b6f
WIP: add create person mutation.
conradwt Dec 12, 2021
989f9f3
Code cleanup.
conradwt Dec 12, 2021
96a5827
Cleanup docs. (#50)
conradwt Dec 13, 2021
da63e1d
Remove esbuild. (#51)
conradwt Dec 14, 2021
119582f
Upgrade to Elixir 1.13.1 and update docs. (#52)
conradwt Dec 15, 2021
00712a7
Update to Erlang 24.2. (#53)
conradwt Dec 15, 2021
a987296
Upgrade docs to use Phoenix 1.6.4. (#54)
conradwt Dec 15, 2021
a0ffd1b
Fix routing and associated docs. (#55)
conradwt Dec 18, 2021
62ad49a
Upgrade docs to use Elixir 1.13.1.
conradwt Dec 19, 2021
760928a
Bump to app 3.3.4. (#56)
conradwt Dec 21, 2021
28af508
Upgrade docs and associated implementation code. (#57)
conradwt Dec 22, 2021
f98c377
Update to PostgreSQL 14.1. (#58)
conradwt Dec 25, 2021
8ef31f0
Upgrade license information. (#59)
conradwt Jan 9, 2022
621cce7
Upgrade-to-elixir-1.13.2-otp-24 (#60)
conradwt Jan 14, 2022
2c219ec
Upgrade to Absinthe 1.7.0.
conradwt Jan 25, 2022
e63eebc
Add initial implementation of create person mutation.
conradwt Jan 26, 2022
3cc36be
WIP: Fix GraphQL directory structure.
conradwt Jan 27, 2022
328dcb6
WIP: add missing files.
conradwt Jan 27, 2022
012b125
Code cleanup.
conradwt Jan 27, 2022
752ef95
Fix failing test.
conradwt Jan 27, 2022
01db6a1
Rename and reorganize context file.
conradwt Feb 7, 2022
0a5088b
Code cleanup.
conradwt Feb 7, 2022
03abf6f
More code cleanup.
conradwt Feb 7, 2022
bf4bd23
Update iex configuration file.
conradwt Feb 7, 2022
d0bc247
Update docs to match implementation.
conradwt Feb 7, 2022
e10c75b
Update alias ordering.
conradwt Feb 7, 2022
a584cfd
Update alias ordering.
conradwt Feb 7, 2022
f57faee
Update software requirements.
conradwt Feb 7, 2022
b27f403
Code cleanup.
conradwt Feb 7, 2022
de8ae45
Add Dataloader support functions.
conradwt Feb 7, 2022
0ced04a
Use traditional resolver until dataloader has been implemented.
conradwt Feb 7, 2022
3848b18
Upgrade to Elixir 1.13.3.
conradwt Feb 10, 2022
f70a2ad
Rename module.
conradwt Feb 20, 2022
d30a6ef
Fix module name.
conradwt Feb 20, 2022
6f35ffc
Add Dataloader example file.
conradwt Feb 24, 2022
0072bd2
Configure IEx to set the charlists.
conradwt Feb 24, 2022
63a6a45
Rename endpoint.
conradwt Feb 24, 2022
62b3a37
Rollback dataloader changes and update MIX config.
conradwt Feb 24, 2022
afc66b9
Merge branch 'main' into add-create-person-mutation
conradwt Feb 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .iex.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
IEx.configure(inspect: [charlists: false])

alias ZeroPhoenix.Accounts
alias ZeroPhoenix.Accounts.{Friendship, Person}

alias ZeroPhoenix.Repo

import Ecto.Query
139 changes: 90 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The purpose of this example is to provide details as to how one would go about u

- Elixir 1.13.2 or newer

- Erlang 24.2.1 or newer
- Erlang 24.2 or newer

- Phoenix 1.6.6 or newer

Expand Down Expand Up @@ -126,28 +126,30 @@ Note: This tutorial was updated on macOS 11.6.3.
5. generate contexts, schemas, and migrations for the `Person` resource

```zsh
mix phx.gen.context Account Person people first_name:string last_name:string username:string email:string
mix phx.gen.context Accounts Person people first_name:string last_name:string username:string email:string
```

6. replace the generated `Person` schema with the following:

`lib/zero_phoenix/account/person.ex`:

```elixir
defmodule ZeroPhoenix.Account.Person do
defmodule ZeroPhoenix.Accounts.Person do
use Ecto.Schema

import Ecto.Changeset
alias ZeroPhoenix.Account.Person
alias ZeroPhoenix.Account.Friendship

alias ZeroPhoenix.Accounts.Friendship
alias ZeroPhoenix.Accounts.Person

schema "people" do
field(:email, :string)
field(:first_name, :string)
field(:last_name, :string)
field(:username, :string)
field :email, :string
field :first_name, :string
field :last_name, :string
field :username, :string

has_many(:friendships, Friendship)
has_many(:friends, through: [:friendships, :friend])
has_many :friendships, Friendship
has_many :friends, through: [:friendships, :friend]

timestamps()
end
Expand All @@ -170,7 +172,7 @@ Note: This tutorial was updated on macOS 11.6.3.
8. generate contexts, schemas, and migrations for the `Friendship` resource

```zsh
mix phx.gen.context Account Friendship friendships person_id:references:people friend_id:references:people
mix phx.gen.context Accounts Friendship friendships person_id:references:people friend_id:references:people
```

9. replace the generated `CreateFriendship` migration with the following:
Expand All @@ -197,20 +199,22 @@ Note: This tutorial was updated on macOS 11.6.3.

10. replace the generated `Friendship` schema with the following:

`lib/zero_phoenix/account/friendship.ex`:
`lib/zero_phoenix/accounts/friendship.ex`:

```elixir
defmodule ZeroPhoenix.Account.Friendship do
defmodule ZeroPhoenix.Accounts.Friendship do
use Ecto.Schema

import Ecto.Changeset
alias ZeroPhoenix.Account.Person
alias ZeroPhoenix.Account.Friendship

alias ZeroPhoenix.Accounts.Friendship
alias ZeroPhoenix.Accounts.Person

@required_fields [:person_id, :friend_id]

schema "friendships" do
belongs_to(:person, Person)
belongs_to(:friend, Person)
belongs_to :person, Person
belongs_to :friend, Person

timestamps()
end
Expand Down Expand Up @@ -261,7 +265,7 @@ Note: This tutorial was updated on macOS 11.6.3.

```zsh
defmodule ZeroPhoenix.Seeds do
alias ZeroPhoenix.Account.{Person, Friendship}
alias ZeroPhoenix.Accounts.{Person, Friendship}
alias ZeroPhoenix.Repo

def run() do
Expand Down Expand Up @@ -375,7 +379,9 @@ Note: This tutorial was updated on macOS 11.6.3.
mix run priv/repo/seeds.exs
```

17. add `absinthe_plug` package to your `mix.exs` dependencies as follows:
17. add `absinthe_plug` and `ataloader` hex package dependencies as follows:

`mix.exs`:

```elixir
defp deps do
Expand All @@ -391,8 +397,10 @@ Note: This tutorial was updated on macOS 11.6.3.
{:gettext, "~> 0.18.2"},
{:jason, "~> 1.2.2"},
{:plug_cowboy, "~> 2.5.2"},
{:absinthe, "~> 1.7.0"},
{:absinthe_plug, "~> 1.5.8"},
{:cors_plug, "~> 2.0.3"}
{:cors_plug, "~> 2.0.3"},
{:dataloader, "~> 1.0.10"}
]
end
```
Expand All @@ -417,42 +425,36 @@ Note: This tutorial was updated on macOS 11.6.3.
plug(ZeroPhoenixWeb.Router)
```

20. add the GraphQL schema which represents our entry point into our GraphQL structure:
20. create the GraphQL directory structure

```zsh
mkdir -p lib/zero_phoenix_web/graphql/{resolvers,schemas/{queries,mutations},types}
```

21. add the GraphQL schema which represents our entry point into our GraphQL structure:

`lib/zero_phoenix_web/graphql/schema.ex`:

```elixir
defmodule ZeroPhoenixWeb.Graphql.Schema do
defmodule ZeroPhoenixWeb.GraphQL.Schema do
use Absinthe.Schema

import_types(ZeroPhoenixWeb.Graphql.Types.Person)
import_types(ZeroPhoenixWeb.GraphQL.Types.Person)

alias ZeroPhoenix.Account.Person
alias ZeroPhoenix.Account
import_types(ZeroPhoenixWeb.GraphQL.Schemas.Queries.Person)

query do
field :person, type: :person do
arg(:id, non_null(:id))

resolve(fn %{id: id}, _info ->
case Account.get_person(id) do
%Person{} = person ->
{:ok, person}

_error ->
{:error, "Person id #{id} not found"}
end
end)
end
import_fields(:person_queries)
end
end
```

21. add our Person type which will be performing queries against:
22. add our Person type which will be performing queries against:

`lib/zero_phoenix_web/graphql/types/person.ex`:

```elixir
defmodule ZeroPhoenixWeb.Graphql.Types.Person do
defmodule ZeroPhoenixWeb.GraphQL.Types.Person do
use Absinthe.Schema.Notation

import Ecto
Expand Down Expand Up @@ -486,7 +488,46 @@ Note: This tutorial was updated on macOS 11.6.3.
end
```

22. add routes for our GraphQL API and GraphiQL browser endpoints:
23. add the `person_queries` object to contain all the queries for a person:

`lib/zero_phoenix_web/graphql/schemas/queries/person.ex`:

```elixir
defmodule ZeroPhoenixWeb.GraphQL.Schemas.Queries.Person do
use Absinthe.Schema.Notation

object :person_queries do
field :person, type: :person do
arg :id, non_null(:id)

resolve(&ZeroPhoenixWeb.GraphQL.Resolvers.PersonResolver.find/3)
end
end
end
```

24. add the `PersonResolver` to fetch the individual fields of our person object:

`lib/zero_phoenix_web/graphql/resolvers/person_resolver.ex`:

```elixir
defmodule ZeroPhoenixWeb.GraphQL.Resolvers.PersonResolver do
alias ZeroPhoenix.Accounts
alias ZeroPhoenix.Accounts.Person

def find(_parent, %{id: id}, _info) do
case Accounts.get_person(id) do
%Person{} = person ->
{:ok, person}

_error ->
{:error, "Person id #{id} not found"}
end
end
end
```

25. add routes for our GraphQL API and GraphiQL browser endpoints:

`lib/zero_phoenix_web/router.ex`:

Expand All @@ -507,30 +548,30 @@ Note: This tutorial was updated on macOS 11.6.3.
if Mix.env() in [:dev, :test] do
forward "/graphiql",
Absinthe.Plug.GraphiQL,
schema: ZeroPhoenixWeb.Graphql.Schema,
schema: ZeroPhoenixWeb.GraphQL.Schema,
json_codec: Jason,
interface: :playground
end

forward "/graphql",
forward "/api",
Absinthe.Plug,
schema: ZeroPhoenixWeb.Graphql.Schema
schema: ZeroPhoenixWeb.GraphQL.Schema
end
```

23. start the server
26. start the server

```zsh
mix phx.server
```

24. navigate to our application within the browser
27. navigate to our application within the browser

```zsh
open http://localhost:4000/graphiql
```

25. enter the below GraphQL query on the left side of the browser window
28. enter the below GraphQL query on the left side of the browser window

```graphql
{
Expand All @@ -549,7 +590,7 @@ Note: This tutorial was updated on macOS 11.6.3.
}
```

26. run the GraphQL query
29. run the GraphQL query

```text
Control + Enter
Expand Down
2 changes: 1 addition & 1 deletion dev/support/seeds.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule ZeroPhoenix.Seeds do
alias ZeroPhoenix.Account.{Person, Friendship}
alias ZeroPhoenix.Accounts.{Person, Friendship}
alias ZeroPhoenix.Repo

def run() do
Expand Down
25 changes: 0 additions & 25 deletions lib/zero_phoenix/account/person.ex

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
defmodule ZeroPhoenix.Account do
defmodule ZeroPhoenix.Accounts do
@moduledoc """
The Account context.
The Accounts context.
"""

import Ecto.Query, warn: false
alias ZeroPhoenix.Repo

alias ZeroPhoenix.Account.Person
alias ZeroPhoenix.Repo
alias ZeroPhoenix.Accounts.Person

@doc """
Returns the list of people.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
defmodule ZeroPhoenix.Account.Friendship do
defmodule ZeroPhoenix.Accounts.Friendship do
use Ecto.Schema

import Ecto.Changeset
alias ZeroPhoenix.Account.Person
alias ZeroPhoenix.Account.Friendship

alias ZeroPhoenix.Accounts.Friendship
alias ZeroPhoenix.Accounts.Person

@required_fields [:person_id, :friend_id]

schema "friendships" do
belongs_to(:person, Person)
belongs_to(:friend, Person)
belongs_to :person, Person
belongs_to :friend, Person

timestamps()
end
Expand Down
27 changes: 27 additions & 0 deletions lib/zero_phoenix/accounts/person.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule ZeroPhoenix.Accounts.Person do
use Ecto.Schema

import Ecto.Changeset

alias ZeroPhoenix.Accounts.Friendship
alias ZeroPhoenix.Accounts.Person

schema "people" do
field :email, :string
field :first_name, :string
field :last_name, :string
field :username, :string

has_many :friendships, Friendship
has_many :friends, through: [:friendships, :friend]

timestamps()
end

@doc false
def changeset(%Person{} = person, attrs) do
person
|> cast(attrs, [:first_name, :last_name, :username, :email])
|> validate_required([:first_name, :last_name, :username, :email])
end
end
Loading