-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Searching for implementations with keys #17
base: main
Are you sure you want to change the base?
Conversation
lib/knigge/implementation.ex
Outdated
def fetch!(%Options{implementation: {:config, otp_app, [key | keys]}}) do | ||
otp_app | ||
|> Application.fetch_env!(key) | ||
|> get_in(keys) | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, this doesn't really play nice with the default
changes from #18.
It would also fail quietly when key
exists but get_in
returns nil
for keys
.
Instead I'd would expect to receive an error along the lines of:
Unable to fetch implementation for
MyFacade
from config of app<otp_app>
under path<keys>
.
The message could be improved upon but I think you catch my drift?
lib/knigge/options.ex
Outdated
@@ -305,7 +305,7 @@ defmodule Knigge.Options do | |||
do_not_delegate: :keyword, | |||
implementation: :module, | |||
otp_app: :atom, | |||
config_key: :atom, | |||
config_key: :keys, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of introducing :keys
I'd argue it's a good opportunity to introduce an "or" mechanism:
config_key: [:atom, {:list_of, :atom}]
Where valid_value?/2
would look like this:
defp valid_value?({:list_of, type}, value),
do: is_list(value) and Enum.all?(value, &valid_value?(type, &1))
defp valid_value?(list, value) when is_list(list),
do: Enum.any?(list, &valid_value?(&1, value))
In addition the transform
function could then be extended to map config_key
to always be a list (by using List.wrap/1
).
Which in turn would simplify the implementation in Implementation.fetch!/1
as there no need for multiple clauses anymore (one for single atom, one for list).
Hey @sascha-wolf what do you think is needed to merge this? I'm available to help if needed. Could really use this feature =) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apart from some cosmetic suggestions and one small concern, LGTM 💙💜❤️🧡💛💚
lib/knigge/implementation.ex
Outdated
def fetch!(%Options{implementation: {:config, otp_app, [key | keys]}, default: default}) do | ||
with nil <- otp_app |> env!(key, default) |> get(keys) do | ||
raise ArgumentError, | ||
message: """ | ||
could not fetch application environment #{inspect([key | keys])} \ | ||
for application #{inspect(otp_app)}\ | ||
""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎨 If it's okay I'd prefer to write it like this:
def fetch!(%Options{implementation: {:config, otp_app, [key | keys]}, default: default}) do | |
with nil <- otp_app |> env!(key, default) |> get(keys) do | |
raise ArgumentError, | |
message: """ | |
could not fetch application environment #{inspect([key | keys])} \ | |
for application #{inspect(otp_app)}\ | |
""" | |
def fetch!(%Options{implementation: {:config, otp_app, [key | keys]}, default: default}) do | |
otp_app | |
|> env!(key, default) | |
|> get(keys) | |
|> case do | |
nil -> | |
raise ArgumentError, | |
"could not fetch application environment #{inspect([key | keys])} for application #{inspect(otp_app)}" | |
implementation -> | |
implementation | |
end |
lib/knigge/options.ex
Outdated
|> with_defaults() | ||
|> transform(with_env: env) | ||
|> with_defaults() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
delegate_at_runtime?
default, since the "environment" spec gets resolved to a boolean in transform/2
.
lib/knigge/options.ex
Outdated
defp valid_value?(:keys, value), | ||
do: is_atom(value) || (is_list(value) && Enum.all?(value, &is_atom/1)) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧹 I think we can drop this now, right?
defp valid_value?(:keys, value), | |
do: is_atom(value) || (is_list(value) && Enum.all?(value, &is_atom/1)) |
Co-authored-by: Sascha Wolf <[email protected]>
2a5cd73
to
402396f
Compare
Hi, Sascha I have made some more changes and incorporated your change requests. I have also updated the Because Let me know if the PR is too big and how we want handle the failing tests. Have a nice day. |
Hey @NickNeck, I've to say the PR currently intimidates me. I'm also not sure why you updated the If you think the project can derive value from the changes to |
defmodule_salted WorkingBehaviour do | ||
use Knigge, | ||
otp_app: :knigge, | ||
config_key: [:sys, :module] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading this test, I think it'd be beneficial for readability to deprecate config_key
in favor of config_path
. The Options
module has a map_deprecated
function (link) which we can use to map config_key
to config_path
while also printing a deprecation warning.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I will add this.
I just update the |
Hello @NickNeck and @sascha-wolf! Now I fetch an implementation module from nested configuration key and pass it to |
I'll try to find some time this week. Life has not been kind lately. |
Hi, Sascha
my suggestion would be to extend the
config_key
option so that a list is also accepted.That would be usefull for
behaviour
s with additional configurations.Example:
What do you think?
Kind regards, Marcus
p.s. Nice work and I love the name of the lib.