2016-04-19 10 views
9

config.exsまたはdev.exs/prod.exs/test.exsのサードパーティ製モジュールを使用している場合、phoenixの設定ファイルがロードされてコンパイルされる方法が問題になります。Elixir/Phoenix:設定ファイルでサードパーティのモジュールを使用するには?

例:JWT認証用にGuardianを設定するには、config.exsJOSE.JWKモジュールをJWK作成/ロード用に使用しようとしています。私はiex -S mix phoenix.serverでコンソールに問題なくモジュールを使用できます。それはもちろん依存関係としてインストールされます。私は取得していますエラーが

** (Mix.Config.LoadError) could not load config config/config.exs 
    ** (UndefinedFunctionError) undefined function JOSE.JWK.from_file/2 (module JOSE.JWK is not available) 

ですこれは、私は無名関数でJOSE.JWK.from_file/2への呼び出しをラップしたときにそれは働く私のconfig.exsのコード

# Configure Guardian for JWT Authentication 
config :guardian, Guardian, 
    allowed_algos: ["HS512"], # optional 
    verify_module: Guardian.JWT, # optional 
    issuer: "MyApp", 
    ttl: { 30, :days }, 
    verify_issuer: true, # optional 
    secret_key: System.get_env("GUARDIAN_KEY_PASSPHRASE") |> JOSE.JWK.from_file(System.get_env("GUARDIAN_KEY_FILE")), 
    serializer: MyApp.GuardianSerializer 

です。しかし、もちろんGuardian.configの値(:secret_keyには)その後、匿名関数自体ではなく、その戻り値である:ガーディアンは、この設定値のための機能を受け入れるため、

# Configure Guardian for JWT Authentication 
config :guardian, Guardian, 
    allowed_algos: ["HS512"], # optional 
    verify_module: Guardian.JWT, # optional 
    issuer: "MyApp", 
    ttl: { 30, :days }, 
    verify_issuer: true, # optional 
    secret_key: fn -> System.get_env("GUARDIAN_KEY_PASSPHRASE") |> JOSE.JWK.from_file(System.get_env("GUARDIAN_KEY_FILE")) end, 
    serializer: MyApp.GuardianSerializer 

これは、この例ではokです。しかし、私はこれが問題になる可能性のある他の状況を想像することができます。

この制限はありますか?何か不足していますか?これを回避する方法はありますか?

答えて

13

依存関係がコンパイルされる前に構成が評価されるため、構成の依存関係のコードを使用することはできません。

理由は簡単です。構成によって依存関係がどのようにコンパイルされるかが変わる可能性があります。まず、何をすべきかを決める必要があります。構成を評価するためにコンパイルします。他のアプリケーションを設定するために依存関係を使用するよりもconfigを使ってコンパイルを操作するほうがはるかに便利で頻繁に行われるので、設定を最初に評価することが決定されました。

+0

依存関係ではなく、アプリケーション自体から関数にアクセスするのと同じ質問が適用されます。これはhttps://github.com/trenpixster/addict/issues/105で痛みを引き起こしています –

+0

本当ですか? 'config:my_app、MyApp.Endpoint、'はどのように動作しますか? – asiniy

+0

@asiniy 'MyApp.Endpoint'は単なるアトムです。それが 'MyApp.Endpoint.foo()'だった場合は、関数呼び出しであり、コンパイルするためには依存モジュールが必要です。 – Emil

1

mixを実行する前にelixirc_paths以外の場所にあるモジュールを最初にコンパイルして、それをエリクセル検索パスに入れると、そのモジュールが見つかります。ちょっとWhatever.foo(:bar)

プレコンパイルをミックスタスクとしてまとめておき、サードパーティのdepを呼び出す前にmixを呼び出してconfig depsが最新であることを確認してください。

configを評価する前にpre-configミックスフックと/またはconfig/libがプリコンパイルされていると便利です。そうしないと、を使用してもモジュールがモジュール化されずにDRYできるようになっても、configsが成長して厄介なコードになります。

ハックアラウンドのもう一つの方法は、値を取得してstdoutに書き込むために必要なだけのアプリを読み込み、ポートを使用して必要な場所に移動することです(Railsはこれを場所で行います)。

関連する問題