1
votes

A couple days ago I saw a post from José Valim Mocks and explicit contracts and decided to implement those patterns into my own project wikix.

Those are my config/*.exs files. As you can see (in test.exs and prod.exs) I defined a couple of env vars "http_client" and "user_agent". This way, when I test the module I use a mock, and when the module goes to production I use a real http client.

The problem is: when I try to use wikix as a dependency in my phoenix app, for some reason mix is ignoring my wikix/config/prod.exs file so the http client (in wikix) is never defined.

In my phoenix app instead of have Wikix.HTTPClient I got nil.HTTPClient.

Here is my phoenix/mix.exs file

    defmodule GraapyApi.Mixfile do
      use Mix.Project

      def project do
        [app: :graapy_api,
         version: "0.0.1",
         elixir: "~> 1.0",
         elixirc_paths: elixirc_paths(Mix.env),
         compilers: [:phoenix, :gettext] ++ Mix.compilers,
         build_embedded: Mix.env == :prod,
         start_permanent: Mix.env == :prod, 
         aliases: aliases, deps: deps
        ]
     end

  # Configuration for the OTP application.
  #
  # Type `mix help compile.app` for more information.
  def application do
    [mod: {GraapyApi, []},
     applications: [:phoenix, :cowboy, :logger, :gettext,
                    :phoenix_ecto, :mongodb_ecto, :wikix]]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
  defp elixirc_paths(_),     do: ["lib", "web"]

  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [
      {:phoenix, "~> 1.1.4"},
      {:mongodb_ecto, ">= 0.0.0"},
      {:phoenix_ecto, "~> 2.0"},
      {:gettext, "~> 0.9"},
      {:cowboy, "~> 1.0"},
      {:dogma, "~> 0.1", only: :dev},
      {:credo, "~> 0.3", only: [:dev, :test]},
      {:wikix, github: "graapy/wikix"}
    ]
  end

  # Aliases are shortcut or tasks specific to the current project.
  # For example, to create, migrate and run the seeds file at once:
  #
  #     $ mix ecto.setup
  #
  # See the documentation for `Mix` for more info on aliases.
  defp aliases do
    ["ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"]
3
Can you post your relevant mix.exs file?vikram7
Many thanks for your time, sure.Juan Jose Tugores

3 Answers

2
votes

This is expected behavior. Parent project (your phoenix app) is not using configuration from deps. If dependencies require configuration you need to specify it in the parent app, so you would need to copy:

config :wikix, http_client: Wikix.HTTPClient
config :wikix, user_agent: [{"User-agent", "tugorez [email protected]"}]

to your Phoenix app.

It is often a good idea to provide a default, so for example in Wikix app you can have something like this:

defmodule Wikix.SomeModule do
  @httpclient Wikix.HTTPClient

  call(first_arg, second_arg, httpclient \\ @httclient) do
    ...

You can now read the configuration and pass the client as last argument just as in the article about mocks.

But also you can make sure that your Phoenix app doesn't have to configure anything and it will use the default client when calling the function without specifying last argument.

Your Phoenix app probably shouldn't even know about Wikix "in memory client", so it makes sense to make such defaults.

0
votes

I can't completely decipher your question but I think the answer to this question might be what you're looking for. Specifically this part:

You can read keyword lists stored in a *.exs file, using Mix.Config.read(path).

0
votes

Many thanks to everyone. tkowal, I took your ideas about default values and I finally implement this:

defmodule Wikix.SomeModule do
  @http_client Application.get_env( :wikix, :http_client, Wikix.HTTPClient)
...

If I'm not wrong the third param in Application.get_env is the default value in case the second one be nil .