Failing Function Call that uses env variables

Hi all!

I’m having trouble with LiveView calling a function with Env properties correctly. This is a bit verbose, thanks in advance for sticking with it if you do!

The error-

[error] GenServer #PID<0.656.0> terminating
** (UndefinedFunctionError) function nil.get/0 is undefined
    nil.get()
    (truck_browser 0.1.0) lib/truck_browser_web/live/truck_info.ex:14: TruckBrowserWeb.TruckInfo.handle_info/2
    (phoenix_live_view 0.17.14) lib/phoenix_live_view/channel.ex:260: Phoenix.LiveView.Channel.handle_info/2

Phoenix will continue to start and terminate many GenServers.

For context- I have an app that looks like this structure wise:

trucks_app/
| ── truck_browser (Phoenix, front end only kind of wrapper for truck_sched.)
| ── truck_sched (All business, API logic, is a dependency in truck_browser)

For example- truck_browser calls a function get_schedule() in truck_sched-

truck_browser_web.ex

defmodule TruckBrowserWeb.TruckInfo do
  use TruckBrowserWeb, :live_view


  def mount(_params, _session, socket) do
    send(self(), :get_data)
    {:ok, assign(socket, data: [])}
  end

  def handle_info(:get_data, socket) do
    data = TruckSched.get_schedule()
    {:noreply, assign(socket, :data, data)}
  end

def render(assigns)...

end

This works fine when and the Phoenix LiveView renders the data when get_schedule() looks simple like-

defmodule TruckSched do

  def get_schedule() do
    url = "https://data.sfgov.org/resource/jjew-r69b.json?"
    headers = [{"Accept", "application/json"}]

    case HTTPoison.get(url, headers) do
      {:ok, %{body: body}} ->
        Poison.decode(body) |> handle_response()

      {:error, reason} ->
        {:error, reason}
    end
  end

  def handle_response({:ok, data}) do
    data
  end

  def handle_response({:error, reason}) do
    {:error, reason}
  end
end

When I start decoupling some of the API and HTTP logic from this function, my problem occurs for LiveView.

This is how my function looks now (and gives me the data correctly in IEx at least)

truck_sched.ex

defmodule TruckSched do

  def api_client, do: Application.get_env(:truck_sched, :api_client)

  def get_schedule do
    api_client().get_data()
  end
end

calls →

truck_sched_api.ex

defmodule TruckSchedAPI do
  @behaviour TruckSchedBehaviour

  def http_adapter, do: Application.get_env(:truck_sched, :http_adapter)

  def get_data() do
    http_adapter().get()
  end

calls →

truck_sched_http_adapter.ex

defmodule TruckSchedHttpAdapter do
  use HTTPoison.Base

  def base_url, do: Application.get_env(:truck_sched, :base_url)

  defp headers do
    [
      {"Accept", "application/json"}
    ]
  end

  def get() do
    case HTTPoison.get(base_url(), headers()) do
      {:ok, %{body: body}} ->
        Poison.decode(body) |> handle_response()

      {:error, reason} ->
        {:error, reason}
    end
  end

  def handle_response({:ok, data}) do
    data
  end

  def handle_response({:error, reason}) do
    {:error, reason}
  end
end

My config files all seem to be working correctly within truck_sched. A small sample of what that looks like-

### config/config.exs-

import Config

config :truck_sched, api_client: TruckSchedAPI

import_config "#{Mix.env()}.exs"

### config/dev.exs-

import Config

config :truck_sched, api_client: TruckSchedAPI

config :truck_sched, http_adapter: TruckSchedHttpAdapter

config :truck_sched, base_url: "https://data.sfgov.org/resource/jjew-r69b.json?"

Am I missing some config elements in the Phoenix app? I tried adding

config :truck_sched, api_client: TruckSchedAPI

in Phoenix’s config, but that didn’t help.

I can tell from the error that my Env variable in truck_sched is returning nil and is not functioning properly. I thought just calling the function from Phoenix would be enough to trigger the correct Env variables for the functions, giving me the correct data, but Im missing something here!

Thanks for any help :wave: