Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot invoke local inside match

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.

like image 800
Nick Tomlin Avatar asked Dec 18 '22 01:12

Nick Tomlin


1 Answers

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
like image 191
chris Avatar answered Dec 25 '22 23:12

chris