Reputation: 29221
I have a simple module responsible for communicating with an API. As a convenience to the user, I allow users to pass a "short" url /my/route
or the full url https://api.mysite.com
and handle it with HTTPoison
's process_url
method:
defmodule MyApp.MyApiHandler do
use HTTPoison.base
@endpoint = "https://api.mysite.com"
def process_url(@endpoint <> _path = url), do: url
def process_url(url), do: @endpoint <> url
end
This works perfectly! Urls that start with the endpoint are unmodified, and those don't have endpoint added.
The issue I'm encountering is when I try to move this endpoint from a module attribute to a method that reads from config at run time:
defmodule MyApp.MyApiHandler do
use HTTPoison.base
def process_url(endpoint() <> _path = url), do: url
def process_url(url), do: endpoint() <> url
defp endpoint do
Application.get_env(:MyApp, __MODULE__)[:endpoint]
end
end
I receive the following error
lib/my_api_handler.ex: cannot invoke local endpoint/0 inside match, called as endpoint()
I'd really prefer to store this config in config (so I can change it per environment). Is there a way to do that while preserving the matching?
The existing SO question for this error doesn't seem to cover my use case (I'm not attempting to assign in the match) but I could also be wrong there.
Upvotes: 4
Views: 2068
Reputation: 222128
The two answers posted already will fetch the env variable at compile time instead of run time which means if you change the value using Application.put_env
, the function will keep on using the old value. The simplest way I can think of to implement this with a value that can change at run time would be to use String.starts_with?/2
:
def process_url(url) do
endpoint = Application.get_env(...)
if String.starts_with?(url, endpoint), do: url, else: endpoint <> url
end
Upvotes: 3
Reputation: 10288
Put it in the module attribute
:
@endpoint Application.get_env(:MyApp, __MODULE__)[:endpoint]
Upvotes: 4
Reputation: 2863
You can define endpoint
as a macro.
E.g,
defmodule Test do
defmacro endpoint do
Application.get_env(:MyApp, __MODULE__)[:endpoint]
end
def process_url(endpoint() <> _path = url), do: url
def process_url(url), do: endpoint() <> url
end
Upvotes: 4