ycherniavskyi
Let’s say I have next controller where {:error, _, _} action result processed by FallbackController:
defmodule SomeProjectWeb.Api.V1.SessionController do
use SomeProjectWeb, :controller
alias SomeProject.Session
alias SomeProject.Session.Otp
alias SomeProjectWeb.Api.V1.CastAndValidateRenderError
alias SomeProjectWeb.Api.V1.FallbackController
alias SomeProjectWeb.Api.V1.{CommonSchema, SessionSchema}
plug(OpenApiSpex.Plug.CastAndValidate, render_error: CastAndValidateRenderError)
action_fallback(FallbackController)
tags(["session"])
def action(conn, _) do
apply(__MODULE__, action_name(conn), [conn, conn.params, conn.body_params])
end
operation(:otp_create,
summary: "otp_create summary",
description: "otp_create description",
requestBody: {
"request body description",
"application/json",
SessionSchema.OtpCreateRequest,
required: true
},
responses: [
ok: {
"ok description",
"application/json",
SessionSchema.OtpCreateResponse
},
unauthorized: "...",
unprocessable_entity: {
"Unprocessable Content, ...",
"application/json",
%Schema{
allOf: [
CommonSchema.ErrorResponse,
%Schema{
type: :object,
properties: %{
code: %Schema{
enum: [
:no_otp_delivery_channel,
:runout_signup_account
]
}
}
}
]
}
},
internal_server_error: {
"Internal Server Error, ...",
"application/json",
%Schema{
allOf: [
CommonSchema.ErrorResponse,
%Schema{
type: :object,
properties: %{
code: %Schema{
enum: [
:external_api,
:demo_account_manager
]
}
}
}
]
}
}
]
)
def otp_create(conn, _params, %{user_email: email} = _body_params) do
case SomeProject.DemoAccountManager.retrieve(email) do
{:ok, i_account} ->
case SomeProject.ExternalApi.create_otp(i_account) do
{200, %{"success" => 1, "type" => "email", "from" => email}} ->
otp = Session.create_otp(%{i_account: i_account, demo: true})
render(conn, otp_id: otp.id, type: "email", from: email)
{500, %{"faultcode" => "channel-error"}} ->
{:error, :unprocessable_entity, :no_otp_delivery_channel}
_ ->
{:error, :internal_server_error, :external_api}
end
{:error, :runout} ->
{:error, :unprocessable_entity, :runout_signup_account}
{:error, _} ->
{:error, :internal_server_error, :demo_account_manager}
end
end
end
For now, I manually sync possible error codes for each result with relative result schema. That is diffidently not convenient and will lead to unsync in the future.
I want to implement some type of module macro that will collect and group all its functions :error results and introduce the helper function to access them.
So I could replace:
internal_server_error: {
"Internal Server Error, ...",
"application/json",
%Schema{
allOf: [
CommonSchema.ErrorResponse,
%Schema{
type: :object,
properties: %{
code: %Schema{
enum: [
:external_api,
:demo_account_manager
]
}
}
}
]
}
}
with:
internal_server_error: {
"Internal Server Error, ...",
"application/json",
%Schema{
allOf: [
CommonSchema.ErrorResponse,
%Schema{
type: :object,
properties: %{
code: %Schema{
enum: error_codes(:otp_create, :internal_server_error)
}
}
}
]
}
}
(for sure such the final helper function could produce a more significant piece of repetitive code, but here I want to highlight its core functionality)
What is the best way to implement such functionality?
Trending in Questions
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
Hi everyone,
I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding.
I sta...
New
Hello,
I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
Documentation
While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
So my question is quite simple and i have found no conclusive answer on forum, google or AI.
Should we use :erlang.float for Integer to ...
New
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apply_graft/2 doesn’t rewrite an add_many sub-workflow’s deps on an add step. Grafted jobs cancel with “upstream job was deleted”
Version...
New
Other Trending Topics
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
Hi there! We created Gust: A task orchestrator inspired by Airflow.
For those who have never heard about Aiflow, it’s a Python-based wor...
New
Hi everyone!
The first release candidate for the Expert language server project is now available!
We’ve published a press release detai...
New
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself.
My main conc...
New
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixirconf-us
- #ai
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #elixirconf-eu
- #metaprogramming
- #hex









