簡體   English   中英

帶有狀態代理的 Elixir 宏

[英]Elixir macro with Agent for state

所以我試圖了解遷移在 Ecto 中是如何工作的。 我的意思不是如何使用它們,而是在代碼中實際發生了什么。 我看到的是,當運行各種宏時,狀態會被泵入代理。

當運行混合任務以遷移數據時,將檢索代理數據並運行適當的 SQL 命令。

這讓我大吃一驚,我不明白在編譯期間代理進程是如何活動的。 好的,所以我有點理解在宏擴展期間,可以運行引用塊之外的任何代碼,包括生成過程,但為什么在編譯/擴展后和實際執行期間它仍然存在?

克里斯

我不明白在編譯期間代理進程是如何活動的。

不是。 宏將 DSL 轉換為調用Ecto.MigrationEcto.Migration.Runner函數的代碼。 這是一個例子。 以下遷移:

defmodule M.Repo.Migrations.CreatePosts do
  use Ecto.Migration

  def change do
    create(:posts) do
      add :title, :string
      add :content, :text
    end
  end
end

編譯成這個 Erlang:

-module('Elixir.M.Repo.Migrations.CreatePosts').

...

change() ->
    _@1 = #{'__struct__' := 'Elixir.Ecto.Migration.Table'} =
          posts,
    'Elixir.Ecto.Migration.Runner':start_command({create,
                          'Elixir.Ecto.Migration':'__prefix__'(_@1)}),
    case case _@1 of
       #{primary_key := _@2} -> _@2;
       _@2 when erlang:is_map(_@2) ->
           erlang:error({badkey, primary_key, _@2});
       _@2 -> _@2:primary_key()
     end
    of
      _@3 when (_@3 =:= nil) or (_@3 =:= false) ->
      _@4 = nil, nil;
      _ ->
      _@4 =
          'Elixir.Ecto.Migration.Runner':repo_config(migration_primary_key,
                             []),
      'Elixir.Ecto.Migration':add(case
                    'Elixir.Access':get(_@4, name, nil)
                      of
                    _@5
                        when (_@5 =:= nil) or
                           (_@5 =:= false) ->
                        id;
                    _@6 -> _@6
                      end,
                      case 'Elixir.Access':get(_@4, type, nil)
                      of
                    _@7
                        when (_@7 =:= nil) or
                           (_@7 =:= false) ->
                        bigserial;
                    _@8 -> _@8
                      end,
                      [{primary_key, true}])
    end,
    'Elixir.Ecto.Migration':add(title, string),
    'Elixir.Ecto.Migration':add(content, text),
    'Elixir.Ecto.Migration.Runner':end_command(),
    _@1.

就算不看Erlang,也能看出來是調用了Ecto.Migration.Runner.start_command ,然后調用了給agent添加數據的函數,最后調用了.end_command 所有這些都發生在執行遷移時的運行時,而不是編譯時。 在編譯時,僅將 DSL 擴展為此代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM