Eiji
October 9, 2022, 10:45am
6
Nothing stops you from writing one generic module and each module for every of your APIs.
Also you can use metaprogramming like:
defmodule Example do
use MyLib, flat_keys: @flat_keys ~w[occupation username]
def parse("birthday", birthday) when is_integer(birthday) do
naive = birthday |> DateTime.from_unix!() |> DateTime.to_naive()
{~w[public_profile birthday], naive}
end
end
Another way is to use an existing library like cozy_params
:
Hey, guys.
Recently, I created a new package called cozy_params for casting and validating params.
It is based on Ecto, and has Ecto-like API.
An example integrating with Phoenix:
defmodule DemoWeb.PageController do
use DemoWeb, :controller
import CozyParams
action_fallback DemoWeb.FallbackController
defparams :product_search do
field :name, :string, required: true
embeds_many :tags do
field :name, :string, required: true
end
end
def index(conn, params) do
…
In above topic I have suggested an interesting ideas for source
and sources
options. Those are already approved and once implemented it would suit your case perfectly.
See also related GitHub issue:
opened 11:31AM - 15 Aug 22 UTC
todo
The initial idea comes from https://elixirforum.com/t/cozy-params-provides-ecto-… like-api-for-casting-and-validating-params/49445/11?u=c4710n.
Following is a copy of the main content which is created by @Eiji7:
```elixir
defmodule Example do
import CozyParams
defparams :structured_params do
field(:age, :integer, required: true)
# simply a field source
field(:name, :string, required: true, source: "full_name")
# with this we could look for a map in "item" param
# and attach extra params that are in wrong nested position
# for example:
# params = %{"item" => %{"id" => 1}, "count" => 1}
embeds_one :item, source: "item", sources: ~w(count) do
field(:count, :integer, required: true)
field(:id, :integer, required: true)
end
# also this may be interesting in really big nested structure
# params = %{"items" => [%{"data" => %{"count" => 1, "id" => 1}}]}
embeds_one :item2, source: ["items", Access.at(0), "data"] do
field(:count, :integer, required: true)
field(:id, :integer, required: true)
end
# of course nothing should stop developers from using sources option on
# embeds_one/embeds_many together with source option on their fields,
# for example:
# params = %{"item_count" => 1, "item_id" => 1}
embeds_one :item3, sources: ~w(item_count item_id) do
field(:count, :integer, required: true, source: "item_count")
field(:id, :integer, required: true, source: "item_id")
end
end
end
# I got idea about source and sources options after I remember that something similar exists in
# ecto already, see: [Optionas section @ Ecto.Schema.field/3](https://hexdocs.pm/ecto/Ecto.Schema.html#field/3-options).
```
1 Like