Open zoedsoupe opened 2 years ago
Yes you can define the schema at runtime and share enum values between schemas.
If it's the same enum used in multiple schemas, you can adapt the example from https://swagger.io/docs/specification/data-models/enums/#reuse and reference a shared enum schema from other schemas.
Any module that exposes a schema/0
function can be used as a schema (https://github.com/open-api-spex/open_api_spex/blob/master/lib/open_api_spex/schema.ex#L144-L148), so you can create a runtime schema like:
defmodule MyApp.Schemas.RuntimeEnumExample do
@behaviour OpenApiSpex.Schema
@impl true
def schema do
%OpenApiSpex.Schema{
title: "RuntimeEnumExample",
description: "A description for this enumeration...",
type: :string,
# get the values at runtime...
enum: Application.get_env(:my_app, :some_runtime_configuration)
}
end
end
Then elsewhere in your schema:
defmodule MyApp.Schemas.ApiResponseExample do
require OpenApiSpex
alias OpenApiSpex.Schema
OpenApiSpex.schema(%{
type: :object,
title: "ApiResponseExample",
description: "A description....",
properties: %{
id: %Schema{type: :string},
status: MyApp.Schemas.RuntimeEnumExample,
}
})
end
Oh, thank you! That's is exactly what we need!
Ok, so I tried some options and now we have this:
defmodule CobrancaWeb.Swagger.Schemas.Financing.Status do
@moduledoc false
alias Cobranca.TermDictionary
@behaviour OpenApiSpex.Schema
@impl true
def schema do
status = TermDictionary.keys(:financing_status)
%OpenApiSpex.Schema{
title: "Status",
description: "Status de Financiamento",
type: :string,
enum: status
}
end
end
However, it still trying to get values from compile time when Registry
and Agent
aren't alive 😕
== Compilation error in file lib/cobranca_web/swagger/schemas/financing/financing.ex==
** (ArgumentError) unknown registry: Cobranca.DictionaryRegistry
(elixir 1.13.4) lib/registry.ex:1347: Registry.key_info!/1
(elixir 1.13.4) lib/registry.ex:227: Registry.whereis_name/2
(elixir 1.13.4) lib/gen_server.ex:1209: GenServer.whereis/1
(elixir 1.13.4) lib/gen_server.ex:1017: GenServer.call/3
lib/cobranca_web/swagger/schemas/financing/status.ex:10: CobrancaWeb.Swagger.Schemas.Financing.Status.schema/0
(open_api_spex 3.11.0) lib/open_api_spex/schema.ex:403: OpenApiSpex.Schema.default/1
(open_api_spex 3.11.0) lib/open_api_spex/schema.ex:327: anonymous fn/2 in OpenApiSpex.Schema.properties/1
(stdlib 3.17) maps.erl:410: :maps.fold_1/3
(open_api_spex 3.11.0) lib/open_api_spex/schema.ex:327: OpenApiSpex.Schema.properties/1
lib/cobranca_web/swagger/schemas/financing/financing.ex:8: (module)
(elixir 1.13.4) lib/kernel/parallel_compiler.ex:346: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/7
Maybe is because OpenApiSpex
is a struct, that are expanded at compile-time too
It looks like this line is the problem: https://github.com/open-api-spex/open_api_spex/blob/4f6b91b7bad9b8125e4c9d7e1ce0a7c6518b2011/lib/open_api_spex/schema.ex#L331
It’s computing the default value of each property at compile time, ~but it appears to discard the results~ 🤔
~Maybe try changing that functions to use Map.keys
instead.~
Edit: sorry I misread the code. It is returning a default value for each property for use in the struct definition.
We might need to add another optional callback to the schema behaviour to avoid evaluating the schema at compile time.
We have some
Agents
that are internal term dictionaries (maps) and the value of some external properties that will be exposed on our API swagger are thoseAgents
(maps) keys.I know schemas are a compile-time feature, so how could I avoid repeating these enums across my source code?