Closed lucazulian closed 1 week ago
This is not a nimble_options issue. You are validating the options at compile time, not at runtime, so what is getting passed to NimbleOptions.validate!/2
there is
iex(1)> quote do: [{"x-consumer-argument", :bool, true}]
[{:{}, [], ["x-consumer-argument", :bool, true]}]
Hence the error. Validate the options after unquoting them:
quote bind_quoted: [options: options]
options = NimbleOptions.validate!(...)
Consumer.start_link(...)
end
This is not a nimble_options issue. You are validating the options at compile time, not at runtime, so what is getting passed to
NimbleOptions.validate!/2
there isiex(1)> quote do: [{"x-consumer-argument", :bool, true}] [{:{}, [], ["x-consumer-argument", :bool, true]}]
Hence the error. Validate the options after unquoting them:
quote bind_quoted: [options: options] options = NimbleOptions.validate!(...) Consumer.start_link(...) end
Hi @whatyouhide, thank you for you response. I see, and the compile-time validation was needed. I consider this a nimble_options issue because I wonder why it handles all the other tuples correctly and not that specific one, knowing that it's an elixir special case.
@lucazulian it's not an Elixir special case. You are treating the AST (representation of the code) as the data structure you want to validate.
start_link/1
in your quote
d code inside __using__
likely won't work anyway, because you'd start a process at compile time (which is when __using__
is invoked) and not at runtime. My guess is that you'd want something like:
defmacro __using__(opts) do
quote bind_quoted: [opts: opts], unquote: false do
# opts π here is injected as AST so `NimbleOptions.validate!` will
# receive the value itself, not the representation of the code
val_opts = NimbleOptions.validate!(opts, Consumer.config_schema())
def start_link do
Consumer.start_link(unquote(val_opts))
end
end
end
Validation still happens at compile-time this way.
@lucazulian it's not an Elixir special case. You are treating the AST (representation of the code) as the data structure you want to validate.
start_link/1
in yourquote
d code inside__using__
likely won't work anyway, because you'd start a process at compile time (which is when__using__
is invoked) and not at runtime. My guess is that you'd want something like:defmacro __using__(opts) do quote bind_quoted: [opts: opts], unquote: false do # opts π here is injected as AST so `NimbleOptions.validate!` will # receive the value itself, not the representation of the code val_opts = NimbleOptions.validate!(opts, Consumer.config_schema()) def start_link do Consumer.start_link(unquote(val_opts)) end end end
Validation still happens at compile-time this way.
Thanks for the clarification!
Whenever I try to pass a 3-element tuple as an argument in the configuration schema, I encounter the following error:
Code usefull to reproduce the issue
Expected Behavior
The tuple provided in arguments: [{"x-consumer-argument", :bool, true}] should be validated correctly based on the schema, which specifies a tuple with types [:string, :atom, :any].
Actual Behavior
NimbleOptions raises an error that indicates the tuple is invalid, specifically for the first element, which expects a string but fails when provided with a valid string because it receives an AST representation.
Additional Context
If you think this is a valuable issue, I have a possible working solution.