[英]Elixir macro with Agent for state
所以我試圖了解遷移在 Ecto 中是如何工作的。 我的意思不是如何使用它們,而是在代碼中實際發生了什么。 我看到的是,當運行各種宏時,狀態會被泵入代理。
當運行混合任務以遷移數據時,將檢索代理數據並運行適當的 SQL 命令。
這讓我大吃一驚,我不明白在編譯期間代理進程是如何活動的。 好的,所以我有點理解在宏擴展期間,可以運行引用塊之外的任何代碼,包括生成過程,但為什么在編譯/擴展后和實際執行期間它仍然存在?
克里斯
我不明白在編譯期間代理進程是如何活動的。
不是。 宏將 DSL 轉換為調用Ecto.Migration
和Ecto.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.