We can't find the internet
Attempting to reconnect
Something went wrong!
Hang in there while we get back on track
Chapter 4: Generating APIs Without Writing Code
Modeling Your Domain
- Goal: expose your domain so others can access it via REST or GraphQL
- We’ll build both JSON REST and GraphQL interfaces
Building a JSON REST Interface
Setup
-
Use Igniter to install
ash_json_api:mix igniter.install ash_json_api -
This adds:
- AshJsonApi Hex package
-
Code/config for
application/vnd.api+json -
TunezWeb.AshJsonApiRouter - New scope in Phoenix router
Adding Artists
-
Extend the Artist resource for the API:
mix ash.extend Tunez.Music.Artist json_api -
Adds
AshJsonApi.Resourceto Artist -
Adds
AshJsonApi.Domainextension forTunez.Music -
Connects domain to
TunezWeb.AshJsonApiRouter
Routes
-
Set API routes in
lib/tunez/music.ex:json_api do routes do base_route "/artists", Tunez.Music.Artist do get :read index :search post :create patch :update delete :destroy end end end -
Check routes with:
mix phx.routes -
Example GET:
http://localhost:4000/api/json/artists/?query=and
Public Attributes
-
Only attributes marked
public? trueare included in API responses -
Example for
Artist:attribute :previous_names, {:array, :string}, public?: true attribute :biography, :string, public?: true -
Calculations/aggregates can be default fields or requested via query parameters:
?fields=name,album_count
Adding Albums
-
Extend the Album resource:
mix ash.extend Tunez.Music.Album json_api -
Set routes in
lib/tunez/music.ex:base_route "/albums", Tunez.Music.Album do post :create patch :update delete :destroy end -
Make necessary attributes public (
name,year_released,cover_image_url) -
Show related albums for an artist:
relationships do has_many :albums, Tunez.Music.Album, public?: true, sort: [year_released: :desc] end -
Include related records in API responses:
json_api do type "artist" includes [:albums] end -
Provide related links:
related(:albums, :read, primary?: true)
Generating API Documentation
-
OpenAPI route:
use AshJsonApi.Router, domains: [Tunez.Music], open_api: "/open_api" -
Swagger UI available at
/api/json/swaggeruiin Phoenix router
Customizing the API
-
Add resource/action descriptions:
resource do description "A person or group of people that makes and releases music." end read :search do description "List Artists, optionally filtering by name." argument :query, :ci_string, description: "Filter artists by name." end -
Set API title and version in
AshJsonApiRouter:open_api_title: "Tunez API Documentation", open_api_version: to_string(Application.spec(:tunez, :vsn)) -
Remove unwanted filters:
derive_filter?(false)
Building a GraphQL Interface
Setup
-
Install
ash_graphqlvia Igniter:mix igniter.install ash_graphql -
Adds:
- AshGraphql & Absinthe configuration
-
/gqlpipeline &/gql/playgroundscope -
TunezWeb.GraphqlSchema&TunezWeb.GraphqlSocket
Adding Artists
-
Extend Artist for GraphQL:
mix ash.extend Tunez.Music.Artist graphql -
Queries:
graphql do queries do get Tunez.Music.Artist, :get_artist_by_id, :read list Tunez.Music.Artist, :search_artists, :search end end -
Mutations:
create Tunez.Music.Artist, :create_artist, :create update Tunez.Music.Artist, :update_artist, :update delete Tunez.Music.Artist, :destroy_artist, :destroy
Adding Albums
-
Extend Album for GraphQL:
mix ash.extend Tunez.Music.Album graphql -
Mutations for albums:
create Tunez.Music.Album, :create_album, :create update Tunez.Music.Album, :update_album, :update destroy Tunez.Music.Album, :destroy_album, :destroy
Customizing GraphQL
-
Remove unwanted fields and set filterable fields:
graphql do type :artist filterable_fields [:album_count, :cover_image_url, :inserted_at, :latest_album_year_released, :updated_at] end