• United States+1
  • United Kingdom+44
  • Afghanistan (‫افغانستان‬‎)+93
  • Albania (Shqipëri)+355
  • Algeria (‫الجزائر‬‎)+213
  • American Samoa+1684
  • Andorra+376
  • Angola+244
  • Anguilla+1264
  • Antigua and Barbuda+1268
  • Argentina+54
  • Armenia (Հայաստան)+374
  • Aruba+297
  • Australia+61
  • Austria (Österreich)+43
  • Azerbaijan (Azərbaycan)+994
  • Bahamas+1242
  • Bahrain (‫البحرين‬‎)+973
  • Bangladesh (বাংলাদেশ)+880
  • Barbados+1246
  • Belarus (Беларусь)+375
  • Belgium (België)+32
  • Belize+501
  • Benin (Bénin)+229
  • Bermuda+1441
  • Bhutan (འབྲུག)+975
  • Bolivia+591
  • Bosnia and Herzegovina (Босна и Херцеговина)+387
  • Botswana+267
  • Brazil (Brasil)+55
  • British Indian Ocean Territory+246
  • British Virgin Islands+1284
  • Brunei+673
  • Bulgaria (България)+359
  • Burkina Faso+226
  • Burundi (Uburundi)+257
  • Cambodia (កម្ពុជា)+855
  • Cameroon (Cameroun)+237
  • Canada+1
  • Cape Verde (Kabu Verdi)+238
  • Caribbean Netherlands+599
  • Cayman Islands+1345
  • Central African Republic (République centrafricaine)+236
  • Chad (Tchad)+235
  • Chile+56
  • China (中国)+86
  • Christmas Island+61
  • Cocos (Keeling) Islands+61
  • Colombia+57
  • Comoros (‫جزر القمر‬‎)+269
  • Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)+243
  • Congo (Republic) (Congo-Brazzaville)+242
  • Cook Islands+682
  • Costa Rica+506
  • Côte d’Ivoire+225
  • Croatia (Hrvatska)+385
  • Cuba+53
  • Curaçao+599
  • Cyprus (Κύπρος)+357
  • Czech Republic (Česká republika)+420
  • Denmark (Danmark)+45
  • Djibouti+253
  • Dominica+1767
  • Dominican Republic (República Dominicana)+1
  • Ecuador+593
  • Egypt (‫مصر‬‎)+20
  • El Salvador+503
  • Equatorial Guinea (Guinea Ecuatorial)+240
  • Eritrea+291
  • Estonia (Eesti)+372
  • Ethiopia+251
  • Falkland Islands (Islas Malvinas)+500
  • Faroe Islands (Føroyar)+298
  • Fiji+679
  • Finland (Suomi)+358
  • France+33
  • French Guiana (Guyane française)+594
  • French Polynesia (Polynésie française)+689
  • Gabon+241
  • Gambia+220
  • Georgia (საქართველო)+995
  • Germany (Deutschland)+49
  • Ghana (Gaana)+233
  • Gibraltar+350
  • Greece (Ελλάδα)+30
  • Greenland (Kalaallit Nunaat)+299
  • Grenada+1473
  • Guadeloupe+590
  • Guam+1671
  • Guatemala+502
  • Guernsey+44
  • Guinea (Guinée)+224
  • Guinea-Bissau (Guiné Bissau)+245
  • Guyana+592
  • Haiti+509
  • Honduras+504
  • Hong Kong (香港)+852
  • Hungary (Magyarország)+36
  • Iceland (Ísland)+354
  • India (भारत)+91
  • Indonesia+62
  • Iran (‫ایران‬‎)+98
  • Iraq (‫العراق‬‎)+964
  • Ireland+353
  • Isle of Man+44
  • Israel (‫ישראל‬‎)+972
  • Italy (Italia)+39
  • Jamaica+1876
  • Japan (日本)+81
  • Jersey+44
  • Jordan (‫الأردن‬‎)+962
  • Kazakhstan (Казахстан)+7
  • Kenya+254
  • Kiribati+686
  • Kosovo+383
  • Kuwait (‫الكويت‬‎)+965
  • Kyrgyzstan (Кыргызстан)+996
  • Laos (ລາວ)+856
  • Latvia (Latvija)+371
  • Lebanon (‫لبنان‬‎)+961
  • Lesotho+266
  • Liberia+231
  • Libya (‫ليبيا‬‎)+218
  • Liechtenstein+423
  • Lithuania (Lietuva)+370
  • Luxembourg+352
  • Macau (澳門)+853
  • Macedonia (FYROM) (Македонија)+389
  • Madagascar (Madagasikara)+261
  • Malawi+265
  • Malaysia+60
  • Maldives+960
  • Mali+223
  • Malta+356
  • Marshall Islands+692
  • Martinique+596
  • Mauritania (‫موريتانيا‬‎)+222
  • Mauritius (Moris)+230
  • Mayotte+262
  • Mexico (México)+52
  • Micronesia+691
  • Moldova (Republica Moldova)+373
  • Monaco+377
  • Mongolia (Монгол)+976
  • Montenegro (Crna Gora)+382
  • Montserrat+1664
  • Morocco (‫المغرب‬‎)+212
  • Mozambique (Moçambique)+258
  • Myanmar (Burma) (မြန်မာ)+95
  • Namibia (Namibië)+264
  • Nauru+674
  • Nepal (नेपाल)+977
  • Netherlands (Nederland)+31
  • New Caledonia (Nouvelle-Calédonie)+687
  • New Zealand+64
  • Nicaragua+505
  • Niger (Nijar)+227
  • Nigeria+234
  • Niue+683
  • Norfolk Island+672
  • North Korea (조선 민주주의 인민 공화국)+850
  • Northern Mariana Islands+1670
  • Norway (Norge)+47
  • Oman (‫عُمان‬‎)+968
  • Pakistan (‫پاکستان‬‎)+92
  • Palau+680
  • Palestine (‫فلسطين‬‎)+970
  • Panama (Panamá)+507
  • Papua New Guinea+675
  • Paraguay+595
  • Peru (Perú)+51
  • Philippines+63
  • Poland (Polska)+48
  • Portugal+351
  • Puerto Rico+1
  • Qatar (‫قطر‬‎)+974
  • Réunion (La Réunion)+262
  • Romania (România)+40
  • Russia (Россия)+7
  • Rwanda+250
  • Saint Barthélemy (Saint-Barthélemy)+590
  • Saint Helena+290
  • Saint Kitts and Nevis+1869
  • Saint Lucia+1758
  • Saint Martin (Saint-Martin (partie française))+590
  • Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)+508
  • Saint Vincent and the Grenadines+1784
  • Samoa+685
  • San Marino+378
  • São Tomé and Príncipe (São Tomé e Príncipe)+239
  • Saudi Arabia (‫المملكة العربية السعودية‬‎)+966
  • Senegal (Sénégal)+221
  • Serbia (Србија)+381
  • Seychelles+248
  • Sierra Leone+232
  • Singapore+65
  • Sint Maarten+1721
  • Slovakia (Slovensko)+421
  • Slovenia (Slovenija)+386
  • Solomon Islands+677
  • Somalia (Soomaaliya)+252
  • South Africa+27
  • South Korea (대한민국)+82
  • South Sudan (‫جنوب السودان‬‎)+211
  • Spain (España)+34
  • Sri Lanka (ශ්‍රී ලංකාව)+94
  • Sudan (‫السودان‬‎)+249
  • Suriname+597
  • Svalbard and Jan Mayen+47
  • Swaziland+268
  • Sweden (Sverige)+46
  • Switzerland (Schweiz)+41
  • Syria (‫سوريا‬‎)+963
  • Taiwan (台灣)+886
  • Tajikistan+992
  • Tanzania+255
  • Thailand (ไทย)+66
  • Timor-Leste+670
  • Togo+228
  • Tokelau+690
  • Tonga+676
  • Trinidad and Tobago+1868
  • Tunisia (‫تونس‬‎)+216
  • Turkey (Türkiye)+90
  • Turkmenistan+993
  • Turks and Caicos Islands+1649
  • Tuvalu+688
  • U.S. Virgin Islands+1340
  • Uganda+256
  • Ukraine (Україна)+380
  • United Arab Emirates (‫الإمارات العربية المتحدة‬‎)+971
  • United Kingdom+44
  • United States+1
  • Uruguay+598
  • Uzbekistan (Oʻzbekiston)+998
  • Vanuatu+678
  • Vatican City (Città del Vaticano)+39
  • Venezuela+58
  • Vietnam (Việt Nam)+84
  • Wallis and Futuna+681
  • Western Sahara (‫الصحراء الغربية‬‎)+212
  • Yemen (‫اليمن‬‎)+967
  • Zambia+260
  • Zimbabwe+263
  • Åland Islands+358
Thanks! We'll be in touch in the next 12 hours
Oops! Something went wrong while submitting the form.

Creating GraphQL APIs Using Elixir Phoenix and Absinthe

Pratik Narode

Full-stack Development

Introduction

GraphQL is a new hype in the Field of API technologies. We have been constructing and using REST API's for quite some time now and started hearing about GraphQL recently. GraphQL is usually described as a frontend-directed API technology as it allows front-end developers to request data in a more simpler way than ever before. The objective of this query language is to formulate client applications formed on an instinctive and adjustable format, for portraying their data prerequisites as well as interactions.

The Phoenix Framework is running on Elixir, which is built on top of Erlang. Elixir core strength is scaling and concurrency. Phoenix is a powerful and productive web framework that does not compromise speed and maintainability. Phoenix comes in with built-in support for web sockets, enabling you to build real-time apps.

Prerequisites:

  1. Elixir & Erlang: Phoenix is built on top of these
  2. Phoenix Web Framework: Used for writing the server application. (It's a well-unknown and lightweight framework in elixir) 
  3. Absinthe: GraphQL library written for Elixir used for writing queries and mutations.
  4. GraphiQL: Browser based GraphQL ide for testing your queries. Consider it similar to what Postman is used for testing REST APIs.

Overview:

The application we will be developing is a simple blog application written using Phoenix Framework with two schemas User and Post defined in Accounts and Blog resp. We will design the application to support API's related to blog creation and management. Assuming you have Erlang, Elixir and mix installed.

Where to Start:

At first, we have to create a Phoenix web application using the following command:

mix phx.new  --no-brunch --no-html
view raw create-app.js hosted with ❤ by GitHub

--no-brunch - do not generate brunch files for static asset building. When choosing this option, you will need to manually handle JavaScript  dependencies if building HTML apps

• --no-html - do not generate HTML views.

Note: As we are going to mostly work with API, we don't need any web pages, HTML views and so the command args  and

Dependencies:

After we create the project, we need to add dependencies in mix.exs to make GraphQL available for the Phoenix application.

defp deps do
[
{:absinthe, "~> 1.3.1"},
{:absinthe_plug, "~> 1.3.0"},
{:absinthe_ecto, "~> 0.1.3"}
]
end

Structuring the Application:

We can used following components to design/structure our GraphQL application:

  1. GraphQL Schemas : This has to go inside lib/graphql_web/schema/schema.ex. The schema definitions your queries and mutations.
  2. Custom types: Your schema may include some custom properties which should be defined inside lib/graphql_web/schema/types.ex

Resolvers: We have to write respective Resolver Function’s that handles the business logic and has to be mapped with respective query or mutation. Resolvers should be defined in their own files. We defined it inside lib/graphql/accounts/user_resolver.ex and lib/graphql/blog/post_resolver.ex folder.

Also, we need to uppdate the router we have to be able to make queries using the GraphQL client in lib/graphql_web/router.ex and also have to create a GraphQL pipeline to route the API request which also goes inside lib/graphql_web/router.ex:

pipeline :graphql do
plug Graphql.Context #custom plug written into lib/graphql_web/plug/context.ex folder
end
scope "/api" do
pipe_through(:graphql) #pipeline through which the request have to be routed
forward("/", Absinthe.Plug, schema: GraphqlWeb.Schema)
forward("/graphiql", Absinthe.Plug.GraphiQL, schema: GraphqlWeb.Schema)
end

Writing GraphQL Queries:

Lets write some graphql queries which can be considered to be equivalent to GET requests in REST. But before getting into queries lets take a look at GraphQL schema we defined and its equivalent resolver mapping:

defmodule GraphqlWeb.Schema do
use Absinthe.Schema
import_types(GraphqlWeb.Schema.Types)
query do
field :blog_posts, list_of(:blog_post) do
resolve(&Graphql.Blog.PostResolver.all/2)
end
field :blog_post, type: :blog_post do
arg(:id, non_null(:id))
resolve(&Graphql.Blog.PostResolver.find/2)
end
field :accounts_users, list_of(:accounts_user) do
resolve(&Graphql.Accounts.UserResolver.all/2)
end
field :accounts_user, :accounts_user do
arg(:email, non_null(:string))
resolve(&Graphql.Accounts.UserResolver.find/2)
end
end
end

You can see above we have defined four queries in the schema. Lets pick a query and see what goes into it :

field :accounts_user, :accounts_user do
arg(:email, non_null(:string))
resolve(&Graphql.Accounts.UserResolver.find/2)
end
view raw query.js hosted with ❤ by GitHub

Above, we have retrieved a particular user using his email address through Graphql query.

  1. arg(:, ): defines an non-null incoming string argument i.e user email for us.
  2. Graphql.Accounts.UserResolver.find/2 : the resolver function that is mapped via schema, which contains the core business logic for retrieving an user.
  3. Accounts_user : the custome defined type which is defined inside lib/graphql_web/schema/types.ex as follows:

object :accounts_user do
field(:id, :id)
field(:name, :string)
field(:email, :string)
field(:posts, list_of(:blog_post), resolve: assoc(:blog_posts))
end
view raw accounts.js hosted with ❤ by GitHub

We need to write a separate resolver function for every query we define. Will go over the resolver function for accounts_user which is present in lib/graphql/accounts/user_resolver.ex file:

defmodule Graphql.Accounts.UserResolver do
alias Graphql.Accounts #import lib/graphql/accounts/accounts.ex as Accounts
def all(_args, _info) do
{:ok, Accounts.list_users()}
end
def find(%{email: email}, _info) do
case Accounts.get_user_by_email(email) do
nil -> {:error, "User email #{email} not found!"}
user -> {:ok, user}
end
end
end

This function is used to list all users or retrieve a particular user using an email address. Let’s run it now using GraphiQL browser. You need to have the server running on port 4000. To start the Phoenix server use:

mix deps.get #pulls all the dependencies
mix deps.compile #compile your code
mix phx.server #starts the phoenix server
view raw server_use.js hosted with ❤ by GitHub

Let’s retrieve an user using his email address via query:

Writing GraphQL Queries

Above, we have retrieved the id, email and name fields by executing accountsUser query with an email address. GraphQL also allow us to define variables which we will show later when writing different mutations.

Let’s execute another query to list all blog posts that we have defined:

GraphQL Queries

 Writing GraphQL Mutations:

Let's write some GraphQl mutations. If you have understood the way graphql queries are written mutations are much simpler and similar to queries and easy to understand. It is defined in the same form as queries with a resolver function. Different mutations we are gonna write are as follow:

  1. create_post:- create a new blog post
  2. update_post :- update a existing blog post
  3. delete_post:- delete an existing blog post

The mutation looks as follows:

defmodule GraphqlWeb.Schema do
use Absinthe.Schema
import_types(GraphqlWeb.Schema.Types)
query do
mutation do
field :create_post, type: :blog_post do
arg(:title, non_null(:string))
arg(:body, non_null(:string))
arg(:accounts_user_id, non_null(:id))
resolve(&Graphql.Blog.PostResolver.create/2)
end
field :update_post, type: :blog_post do
arg(:id, non_null(:id))
arg(:post, :update_post_params)
resolve(&Graphql.Blog.PostResolver.update/2)
end
field :delete_post, type: :blog_post do
arg(:id, non_null(:id))
resolve(&Graphql.Blog.PostResolver.delete/2)
end
end
end
end

Let's run some mutations to create a post in GraphQL:

Writing GraphQL Mutations

Notice the method is POST and not GET over here.

Let's dig into update mutation function :

field :update_post, type: :blog_post do
arg(:id, non_null(:id))
arg(:post, :update_post_params)
resolve(&Graphql.Blog.PostResolver.update/2)
end
view raw mutation.js hosted with ❤ by GitHub

Here, update post takes two arguments as input ,  non null id and a post parameter of type update_post_params that holds the input parameter values to update. The mutation is defined in lib/graphql_web/schema/schema.ex while the input parameter values are defined in lib/graphql_web/schema/types.ex —

input_object :update_post_params do
field(:title, :string)
field(:body, :string)
field(:accounts_user_id, :id)
end

The difference with previous type definitions is that it’s defined as input_object instead of object.

The corresponding resolver function is defined as follows :

def update(%{id: id, post: post_params}, _info) do
case find(%{id: id}, _info) do
{:ok, post} -> post |> Blog.update_post(post_params)
{:error, _} -> {:error, "Post id #{id} not found"}
end
end
view raw resolver.js hosted with ❤ by GitHub

     

GraphQL Functions

Here we have defined a query parameter to specify the id of the blog post to be updated.

Conclusion

This is all you need, to write a basic GraphQL server for any Phoenix application using Absinthe.  

References:

  1. https://www.howtographql.com/graphql-elixir/0-introduction/
  2. https://pragprog.com/book/wwgraphql/craft-graphql-apis-in-elixir-with-absinthe
  3. https://itnext.io/graphql-with-elixir-phoenix-and-absinthe-6b0ffd260094
Get the latest engineering blogs delivered straight to your inbox.
No spam. Only expert insights.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings

Creating GraphQL APIs Using Elixir Phoenix and Absinthe

Introduction

GraphQL is a new hype in the Field of API technologies. We have been constructing and using REST API's for quite some time now and started hearing about GraphQL recently. GraphQL is usually described as a frontend-directed API technology as it allows front-end developers to request data in a more simpler way than ever before. The objective of this query language is to formulate client applications formed on an instinctive and adjustable format, for portraying their data prerequisites as well as interactions.

The Phoenix Framework is running on Elixir, which is built on top of Erlang. Elixir core strength is scaling and concurrency. Phoenix is a powerful and productive web framework that does not compromise speed and maintainability. Phoenix comes in with built-in support for web sockets, enabling you to build real-time apps.

Prerequisites:

  1. Elixir & Erlang: Phoenix is built on top of these
  2. Phoenix Web Framework: Used for writing the server application. (It's a well-unknown and lightweight framework in elixir) 
  3. Absinthe: GraphQL library written for Elixir used for writing queries and mutations.
  4. GraphiQL: Browser based GraphQL ide for testing your queries. Consider it similar to what Postman is used for testing REST APIs.

Overview:

The application we will be developing is a simple blog application written using Phoenix Framework with two schemas User and Post defined in Accounts and Blog resp. We will design the application to support API's related to blog creation and management. Assuming you have Erlang, Elixir and mix installed.

Where to Start:

At first, we have to create a Phoenix web application using the following command:

mix phx.new  --no-brunch --no-html
view raw create-app.js hosted with ❤ by GitHub

--no-brunch - do not generate brunch files for static asset building. When choosing this option, you will need to manually handle JavaScript  dependencies if building HTML apps

• --no-html - do not generate HTML views.

Note: As we are going to mostly work with API, we don't need any web pages, HTML views and so the command args  and

Dependencies:

After we create the project, we need to add dependencies in mix.exs to make GraphQL available for the Phoenix application.

defp deps do
[
{:absinthe, "~> 1.3.1"},
{:absinthe_plug, "~> 1.3.0"},
{:absinthe_ecto, "~> 0.1.3"}
]
end

Structuring the Application:

We can used following components to design/structure our GraphQL application:

  1. GraphQL Schemas : This has to go inside lib/graphql_web/schema/schema.ex. The schema definitions your queries and mutations.
  2. Custom types: Your schema may include some custom properties which should be defined inside lib/graphql_web/schema/types.ex

Resolvers: We have to write respective Resolver Function’s that handles the business logic and has to be mapped with respective query or mutation. Resolvers should be defined in their own files. We defined it inside lib/graphql/accounts/user_resolver.ex and lib/graphql/blog/post_resolver.ex folder.

Also, we need to uppdate the router we have to be able to make queries using the GraphQL client in lib/graphql_web/router.ex and also have to create a GraphQL pipeline to route the API request which also goes inside lib/graphql_web/router.ex:

pipeline :graphql do
plug Graphql.Context #custom plug written into lib/graphql_web/plug/context.ex folder
end
scope "/api" do
pipe_through(:graphql) #pipeline through which the request have to be routed
forward("/", Absinthe.Plug, schema: GraphqlWeb.Schema)
forward("/graphiql", Absinthe.Plug.GraphiQL, schema: GraphqlWeb.Schema)
end

Writing GraphQL Queries:

Lets write some graphql queries which can be considered to be equivalent to GET requests in REST. But before getting into queries lets take a look at GraphQL schema we defined and its equivalent resolver mapping:

defmodule GraphqlWeb.Schema do
use Absinthe.Schema
import_types(GraphqlWeb.Schema.Types)
query do
field :blog_posts, list_of(:blog_post) do
resolve(&Graphql.Blog.PostResolver.all/2)
end
field :blog_post, type: :blog_post do
arg(:id, non_null(:id))
resolve(&Graphql.Blog.PostResolver.find/2)
end
field :accounts_users, list_of(:accounts_user) do
resolve(&Graphql.Accounts.UserResolver.all/2)
end
field :accounts_user, :accounts_user do
arg(:email, non_null(:string))
resolve(&Graphql.Accounts.UserResolver.find/2)
end
end
end

You can see above we have defined four queries in the schema. Lets pick a query and see what goes into it :

field :accounts_user, :accounts_user do
arg(:email, non_null(:string))
resolve(&Graphql.Accounts.UserResolver.find/2)
end
view raw query.js hosted with ❤ by GitHub

Above, we have retrieved a particular user using his email address through Graphql query.

  1. arg(:, ): defines an non-null incoming string argument i.e user email for us.
  2. Graphql.Accounts.UserResolver.find/2 : the resolver function that is mapped via schema, which contains the core business logic for retrieving an user.
  3. Accounts_user : the custome defined type which is defined inside lib/graphql_web/schema/types.ex as follows:

object :accounts_user do
field(:id, :id)
field(:name, :string)
field(:email, :string)
field(:posts, list_of(:blog_post), resolve: assoc(:blog_posts))
end
view raw accounts.js hosted with ❤ by GitHub

We need to write a separate resolver function for every query we define. Will go over the resolver function for accounts_user which is present in lib/graphql/accounts/user_resolver.ex file:

defmodule Graphql.Accounts.UserResolver do
alias Graphql.Accounts #import lib/graphql/accounts/accounts.ex as Accounts
def all(_args, _info) do
{:ok, Accounts.list_users()}
end
def find(%{email: email}, _info) do
case Accounts.get_user_by_email(email) do
nil -> {:error, "User email #{email} not found!"}
user -> {:ok, user}
end
end
end

This function is used to list all users or retrieve a particular user using an email address. Let’s run it now using GraphiQL browser. You need to have the server running on port 4000. To start the Phoenix server use:

mix deps.get #pulls all the dependencies
mix deps.compile #compile your code
mix phx.server #starts the phoenix server
view raw server_use.js hosted with ❤ by GitHub

Let’s retrieve an user using his email address via query:

Writing GraphQL Queries

Above, we have retrieved the id, email and name fields by executing accountsUser query with an email address. GraphQL also allow us to define variables which we will show later when writing different mutations.

Let’s execute another query to list all blog posts that we have defined:

GraphQL Queries

 Writing GraphQL Mutations:

Let's write some GraphQl mutations. If you have understood the way graphql queries are written mutations are much simpler and similar to queries and easy to understand. It is defined in the same form as queries with a resolver function. Different mutations we are gonna write are as follow:

  1. create_post:- create a new blog post
  2. update_post :- update a existing blog post
  3. delete_post:- delete an existing blog post

The mutation looks as follows:

defmodule GraphqlWeb.Schema do
use Absinthe.Schema
import_types(GraphqlWeb.Schema.Types)
query do
mutation do
field :create_post, type: :blog_post do
arg(:title, non_null(:string))
arg(:body, non_null(:string))
arg(:accounts_user_id, non_null(:id))
resolve(&Graphql.Blog.PostResolver.create/2)
end
field :update_post, type: :blog_post do
arg(:id, non_null(:id))
arg(:post, :update_post_params)
resolve(&Graphql.Blog.PostResolver.update/2)
end
field :delete_post, type: :blog_post do
arg(:id, non_null(:id))
resolve(&Graphql.Blog.PostResolver.delete/2)
end
end
end
end

Let's run some mutations to create a post in GraphQL:

Writing GraphQL Mutations

Notice the method is POST and not GET over here.

Let's dig into update mutation function :

field :update_post, type: :blog_post do
arg(:id, non_null(:id))
arg(:post, :update_post_params)
resolve(&Graphql.Blog.PostResolver.update/2)
end
view raw mutation.js hosted with ❤ by GitHub

Here, update post takes two arguments as input ,  non null id and a post parameter of type update_post_params that holds the input parameter values to update. The mutation is defined in lib/graphql_web/schema/schema.ex while the input parameter values are defined in lib/graphql_web/schema/types.ex —

input_object :update_post_params do
field(:title, :string)
field(:body, :string)
field(:accounts_user_id, :id)
end

The difference with previous type definitions is that it’s defined as input_object instead of object.

The corresponding resolver function is defined as follows :

def update(%{id: id, post: post_params}, _info) do
case find(%{id: id}, _info) do
{:ok, post} -> post |> Blog.update_post(post_params)
{:error, _} -> {:error, "Post id #{id} not found"}
end
end
view raw resolver.js hosted with ❤ by GitHub

     

GraphQL Functions

Here we have defined a query parameter to specify the id of the blog post to be updated.

Conclusion

This is all you need, to write a basic GraphQL server for any Phoenix application using Absinthe.  

References:

  1. https://www.howtographql.com/graphql-elixir/0-introduction/
  2. https://pragprog.com/book/wwgraphql/craft-graphql-apis-in-elixir-with-absinthe
  3. https://itnext.io/graphql-with-elixir-phoenix-and-absinthe-6b0ffd260094

Did you like the blog? If yes, we're sure you'll also like to work with the people who write them - our best-in-class engineering team.

We're looking for talented developers who are passionate about new emerging technologies. If that's you, get in touch with us.

Explore current openings