2017-11-20 5 views
0

Ich möchte meine Konten Kontextfunktionen in ihre eigenen Dateien, dann importieren Sie sie in den Kontext, so dass ich die App.Accounts in meinen Controllern Alias ​​und verwenden Sie die Funktionen Diese wurden in den Kontext importiert.Elixir: Wie Alias ​​ein Modul, das nur eine Ladung von Funktionen importiert

Siehe unten für die grobe Einstellung, nach der ich bin.

defmodule App.Accounts.UserAPI do 
    alias App.Accounts.User 

    def get_user!(id), do: User.get!(User, id) end 

    defmacro __using__(_) do 
    import App.Accounts.UserAPI 
end 

defmodule App.Accounts do 
    alias App.Accounts.UserAPI 
    use UserAPI 
end 

defmodule AppWeb.UserController do 
    alias App.Accounts 

    IO.inspect Accounts.module_info 
    # [ 
    # module: Ev2.Accounts, 
    # exports: [__info__: 1, module_info: 0, module_info: 1], 
    # attributes: [vsn: [234644860605005629180170678994286615550]], 
    # compile: [options: [:debug_info], version: '7.0.4', 
    # source: '/Users/.../accounts.ex'], 
    # native: false, 
    # md5: <<176, 134, 244, 210, 70, 244, 89, 41, 130, 7, 134, 109, 55, 131, 27, 254>> 
    # ] 
    def index(conn, %{"id" => id}) do 
    Accounts.get_user(id) # Accounts.get_user/1 is not defined 
    end 
end 

Ich habe zur Zeit arbeiten sie durch die gesamte App.UserAPI in __using__ Makro und Zitate Einwickeln, aber das fühlt sich ausführlich und Verpackung in Zitat scheint mir daran zu hindern, Utility-Funktionen innerhalb des UserAPI aufrufen.

Warum erscheinen die UserAPI Funktionen nicht in den Accounts.module_info Exporten? Und was ist der "richtige" Weg, dies zu tun?

Danke!

Antwort

2

Das Problem ist, dass importierte Funktionen nicht von einem Modul exportiert werden. Sie sind nur im Kontext des Imports verfügbar. Sie möchten importierte Funktionen re-exportieren. Es gibt zwei Möglichkeiten, an die ich denken kann.

  1. Was Sie gerade tun, nach Ihrer Beschreibung: alle Funktionen in einem Zitat-Block in __using__ definieren:

    defmodule App.Accounts.UserAPI do 
        defmacro __using__(_) do 
        quote do 
         alias App.Accounts.User 
    
         def get_user!(id), do: User.get!(User, id) end 
        end 
        end 
    end 
    
  2. Verwenden defdelegate, um eine Funktion zu definieren, die nur eine andere Funktion aufruft:

    defmodule App.Accounts.UserAPI do 
        def get_user!(id), do: User.get!(User, id) end 
    
        defmacro __using__(_) do 
        quote do 
         defdelegate :get_user!(id), to: App.Accounts.UserAPI 
        end 
        end 
    end 
    

In beiden Fällen wird ein use App.Accounts.UserAPI wird tun, was Sie wollen.

Verwandte Themen