Worker.__struct__/0 is undefined, cannot expand struct Worker

Hi all

I have following struct definition:

  @enforce_keys [:uri, :user, :password]
  defstruct [:uri, :user, :password]

and method definition:

  def request(:get, url, struct = %Worker{}) do
    auth = [basic_auth: {struct.user, struct.password}]
    HTTPoison.get(url, %{"Accept" => "application/json"}, [hackney: auth])
  end

Then I’ve got following compiler error:

Worker.__struct__/0 is undefined, cannot expand struct Worker

What am I doing wrong?

Thanks

Could you provide the code for the module where you define the struct, please? You might have defined it in Something.Something.Worker. In such a case if you don’t alias it, the compiler won’t be able to expand it.

btw, consider pattern-matching in the function head. Sometimes it makes the code cleaner:

def request(:get, url, %Worker{user: user, password: password}) do
   auth = [basic_auth: {user, password}]
   HTTPoison.get(url, %{"Accept" => "application/json"}, [hackney: auth])
end
1 Like

Here we go, the whole module

defmodule SapOdataService.Worker do

  @enforce_keys [:uri, :user, :password]
  defstruct [:uri, :user, :password]


  def request(:get, %Worker{uri: sUri, user: sUser, password: sPassword}, mHttpHeaders \\ %{}) do
    lAuth = [basic_auth: {sUser, sPassword}]
    mHeaders = Map.merge(mHttpHeaders, %{"Accept" => "application/json"})
    HTTPoison.get(uri, mHeaders, [hackney: auth])
  end

end

Modules do not automatically alias themselves. You either need %SapOdataService.Worker{} or perhaps more idiomatically %__MODULE__{}.

As an aside, camel case hungarian notation for variable names is not the most idiomatic.

2 Likes
defmodule SapOdataService.Worker do
  @enforce_keys [:uri, :user, :password]
  defstruct [:uri, :user, :password]


  def request(:get, %SapOdataService.Worker{uri: uri, user: user, password: password}, http_headers \\ %{}) do
    auth = [basic_auth: {user, password}]
    headers = Map.merge(http_headers, %{"Accept" => "application/json"})
    HTTPoison.get(uri, headers, [hackney: auth])
  end

end

This should work.

1 Like

Why the compiler need SapOdataService.Worker instead of Worker? There is in they own module.

I don’t know for sure, but I would guess that’s because in elixir explicitness is preferred. You can always use %__MODULE__{}, as @benwilson512 has already pointed out. That way, the __MODULE__ form will be substituted with the full module name (which will also be prefixed by Elixir.) at compile time.

Thanks so much.

__MODULE__ is the way to say “this current module”. Other than that it’s just the normal aliasing rules.

1 Like