chrismccord / mailgun

Elixir Mailgun Client
MIT License
194 stars 95 forks source link

Enable runtime loading of config #26

Closed phanimahesh closed 8 years ago

phanimahesh commented 8 years ago

Currently the __using__ macro expects the config, and the values are evaluated at compile time and persisted. This does not fit well with a typical deployment strategy where configuration is injected through environment variables or config files just before startup.

This change retains backward compatibility and allows any module use ing Mailgun.Client to define a function conf/0 that will return a keyword list. This function for instance may read the values from application config. To illustrate,

use Mailgun.Client, domain: Application.get_env(:library, :mailgun_domain),
                    key: Application.get_env(:library, :mailgun_key),
                    mode: Application.get_env(:library, :mailgun_mode),
                    test_file_path: Application.get_env(:library, :mailgun_test_file_path)

will use the config values present at compile time, but with the change in this commit, if we instead do

use Mailgun.Client

def conf do
  [
    domain: Application.get_env(:library, :mailgun_domain),
    key: Application.get_env(:library, :mailgun_key),
    mode: Application.get_env(:library, :mailgun_mode),
    test_file_path: Application.get_env(:library, :mailgun_test_file_path)
  ]
end

the configuration will be read at runtime, which is probably what everyone using this library wants.

This is in response to discussion at https://groups.google.com/forum/#!topic/elixir-lang-talk/OzHSkE328Js

Zensavona commented 8 years ago

Wholeheartedly +1 this. Thanks @phanimahesh

tispratik commented 8 years ago

Is there any consensus on this?

chrismccord commented 8 years ago

This should work today. Please re-open if you still have issues:

@config domain: Application.get_env(:library, :mailgun_domain),
        key: Application.get_env(:library, :mailgun_key),
        mode: Application.get_env(:library, :mailgun_mode),
        test_file_path: Application.get_env(:library, :mailgun_test_file_path)
use Mailgun.Client, @config
phanimahesh commented 8 years ago

@chrismccord Nope, that won't work. @ tags are also evaluated at compile time. To verify, set some configuration, build a release using exrm or any other release tool, and change the config in sys.config that gets generated. The updated values will not be picked up by Mailgun.

tispratik commented 8 years ago

Thats not working for me :( I tried

  @config domain: Application.get_env(:library, :mailgun_domain),
          key: Application.get_env(:library, :mailgun_key)
  use Mailgun.Client, @config

and

  @config domain: Application.get_env(:myapp, :mailgun_domain),
          key: Application.get_env(:myapp, :mailgun_key)
  use Mailgun.Client, @config

Where "myapp" is my app name.

tispratik commented 8 years ago

This works for me now. I was mistakenly not putting the mailgun prefix "https://api.mailgun.net/v3/".

config :myapp, mailgun_domain: "https://api.mailgun.net/v3/" <> System.get_env("MAILGUN_DOMAIN")

bhserna commented 8 years ago

It is not working for me either =(

I tried this...

defmodule MyMailer do
  @config [
    domain: Application.get_env(:myapp, :mailgun_domain),
    key: Application.get_env(:myapp, :mailgun_key)
  ]

  use Mailgun.Client, @config

  def config do
    @config
  end
end

And after deploying to heroku, I run heroku run iex -S mix to enter the heroku console...

And there I asks for the config of MyMailer doing...

MyMailer.config #  And I got => [domain: nil, key: nil]

But if I asks for the mailgun key...

Application.get_env(:myapp, :mailgun_key) # => "--my key--"

I actually got the keys.

... So I think like @phanimahesh that the problem is that config is evaluated at compile time and at that time the values are not available.

bhserna commented 8 years ago

What I am doing for now, is to call directly Mailgun.Client.send_email/2 like this...

defmodule MyMailer do

  def notification do
    Mailgun.Client.send_email config,
      to: "an@email.com", 
      from: "other@email.com",
      text: "Hola"
  end

  def config do
    [domain: Application.get_env(:myapp, :mailgun_domain),
      key: Application.get_env(:myapp, :mailgun_key)]
  end
end

This function is not documented as "public", but I think is not that bad make it public.

tispratik commented 8 years ago

This is what my current working config looks like:

defmodule Myapp.Mailer do
  @config domain: Application.get_env(:myapp, :mailgun_domain),
          key: Application.get_env(:myapp, :mailgun_key)
          # mode: :test,
          # test_file_path: "mail.json"
  use Mailgun.Client, @config

I had to hardcode my keys in the prod.exs and dev.exs like below:

config :myapp, mailgun_domain: "https://api.mailgun.net/v3/<my-mailgun-domain>",
               mailgun_key: "<my-mailgun-key>"

Make sure to use your correct app name. Mine is :myapp all lower case.