So hey you, it looks like you are interested in Elixir and Phoenix.💧
I've been learning Elixir over the past six months and this a fast tutorial of how you can version your API just using Elixir and Phoenix.🦅
I will not provide any reason for you do that in your API, right now I do have intention to work with Elixir and Phoenix but I'm just studying because of my interest in functional programming, I'm writing it because I want to practice my English and this is my first article.
Creating the project for our use case
mix phx.new hello_version --no-live --no-dashboard --no-html
Quick explanation about the command: we are passing the flags: --no-live
because we are not using LiveView, we don't need the dashboard for monitoring so --no-dashboard
and least but not last: --no-html
Running the project
So if you run your project with:
cd hello_version && iex -S mix phx.server
If I'm not wrong (and I hope so) you will see this strange screen:
That's why we setted for no dashboard, no html and no liveview, if you check your router.ex
you will see it is way more clear than a standard router.ex
from the command mix phx.new new_project
Generating our controllers and views
To generate our controllers and views, we just need one command:
mix phx.gen.json Content Quotation quotations quote:text author:string book:string
Another quick explanation: using mix phx.gen.json
we are generating only the json response for our controllers and views without render or generate HTML and LiveView
After that you will see this in your terminal:
Just add to our router.ex
inside your api scope:
scope "/api", HelloVersionWeb do
pipe_through :api
resources "/quotations", QuotationController, except: [:new, :edit]
end
After that run:
mix ecto.migrate
And if you do all correctly you should be able to see this screen after the 2 steps earlier
We will also need create some quotations, so let's use HTTPie in terminal for that
But you can create with Postman, Insomnia, whatever you want.
Take a deep breath
Ok, I don't know if I'm going to fast or if it's good but let's go to what interest
So hipothetically you are testing the users are not able to use the DELETE verb in your endpoint, so you want to test it with a few users.
You had to change your router.ex
to:
scope "/api", HelloVersionWeb do
pipe_through :api
resources "/quotations", QuotationController, except: [:new, :edit, :delete]
end
Look closely and you will see and you type mix phx.routes
is not anymore listed on the routes.
So you want to apply to the test version let's call it t (I'm not a mathematician).
So for versioning you will need to declare your scope api as the :api
Then you will have to create a new scope, so putting all together it will be:
scope "/api", HelloVersionWeb, as: :api do
pipe_through :api
resources "/quotations", QuotationController, except: [:new, :edit, :delete]
scope "/t", Api.T, as: :t do
resources "/quotations", QuotationController, except: [:new, :edit]
end
end
I will also remove the delete method created by the mix phx.gen.json
command
defmodule HelloVersionWeb.QuotationController do
use HelloVersionWeb, :controller
alias HelloVersion.Content
alias HelloVersion.Content.Quotation
action_fallback HelloVersionWeb.FallbackController
def index(conn, _params) do
quotations = Content.list_quotations()
render(conn, :index, quotations: quotations)
end
def create(conn, %{"quotation" => quotation_params}) do
with {:ok, %Quotation{} = quotation} <- Content.create_quotation(quotation_params) do
conn
|> put_status(:created)
|> put_resp_header("location", ~p"/api/quotations/#{quotation}")
|> render(:show, quotation: quotation)
end
end
def show(conn, %{"id" => id}) do
quotation = Content.get_quotation!(id)
render(conn, :show, quotation: quotation)
end
def update(conn, %{"id" => id, "quotation" => quotation_params}) do
quotation = Content.get_quotation!(id)
with {:ok, %Quotation{} = quotation} <- Content.update_quotation(quotation, quotation_params) do
render(conn, :show, quotation: quotation)
end
end
end
Ok now we will need a new directory called api inside the controllers folder and a t folder inside the api folder
Like this:
The QuotationController inside the Api/T folder
defmodule HelloVersionWeb.Api.T.QuotationController do
use HelloVersionWeb, :controller
alias HelloVersion.Content
alias HelloVersion.Content.Quotation
action_fallback HelloVersionWeb.FallbackController
def index(conn, _params) do
quotations = Content.list_quotations()
render(conn, :index, quotations: quotations)
end
def create(conn, %{"quotation" => quotation_params}) do
with {:ok, %Quotation{} = quotation} <- Content.create_quotation(quotation_params) do
conn
|> put_status(:created)
|> put_resp_header("location", ~p"/api/quotations/#{quotation}")
|> render(:show, quotation: quotation)
end
end
def show(conn, %{"id" => id}) do
quotation = Content.get_quotation!(id)
render(conn, :show, quotation: quotation)
end
def update(conn, %{"id" => id, "quotation" => quotation_params}) do
quotation = Content.get_quotation!(id)
with {:ok, %Quotation{} = quotation} <- Content.update_quotation(quotation, quotation_params) do
render(conn, :show, quotation: quotation)
end
end
def delete(conn, %{"id" => id}) do
quotation = Content.get_quotation!(id)
with {:ok, %Quotation{}} <- Content.delete_quotation(quotation) do
send_resp(conn, :no_content, "")
end
end
end
So for a better study I added a little more than one quote, so I have these 4 quotes:
So after that if want to delete, I'm not being able to use anymore the endpoint and receiving an error message which can be personalized in the fallback controller.
So that's it people from functional and Elixir, thank you for your time. See ya 👋
Top comments (0)