gpt4 book ai didi

elixir - 如何在包含的模块中获取调用方模块名称?

转载 作者:行者123 更新时间:2023-12-01 01:52:32 25 4
gpt4 key购买 nike

如何在包含的 MyApp.MyUniversalModule 中获取调用者模块并通过 field_name 参数获取?

defmodule MyApp.MyUniversalModule do
def gen_and_check_unique(changeset, field_name) do
token = random_string()
# MyApp.MyQueryableModule |> Repo.get_by(field_name, token)
end

def random_string(length \\ 8) do
:crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length)
end
end

defmodule MyApp.MyQueryableModule do
use MyApp.Web, :model
import MyApp.MyUniversalModule

schema "items" do
field :name, :string
field :token, :string
end

def changeset(model, params) do
model
|> cast(params, ~w(name), ~w())
|> gen_and_check_unique(:token)
end
end

最佳答案

编辑:虽然这个答案回答了问题的标题,但正如@stephen_m 的回答所指出的那样,您的代码在几个地方是不正确的。


虽然你can在运行时获取调用堆栈并从中提取调用模块,这将是低效的,通常不推荐。 Elixir 中惯用的方法是使用宏和 __using__ 钩子(Hook)。 Ecto uses the same method for Repo以及许多其他模块。

基本上,您在 __using__ 宏的引号内定义了所有要注入(inject)到调用方模块中的函数。在这种情况下,它看起来像(未经测试):

defmodule MyApp.MyUniversalModule do
defmacro __using__(_opts) do
quote do
def gen_and_check_unique(changeset, field_name) do
token = random_string()
__MODULE__ |> Repo.get_by(field_name, token)
end

def random_string(length \\ 8) do
:crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length)
end
end
end
end

然后,在 MyApp.MyQueryableModule 中,更改:

import MyApp.MyUniversalModule

use MyApp.MyUniversalModule

你可能不想用 random_string 污染调用模块,在这种情况下你可以这样做(同样未经测试):

defmodule MyApp.MyUniversalModule do
defmacro __using__(_opts) do
quote do
def gen_and_check_unique(changeset, field_name) do
token = MyApp.MyUniversalModule.random_string()
__MODULE__ |> Repo.get_by(field_name, token)
end
end
end

def random_string(length \\ 8) do
:crypto.strong_rand_bytes(length) |> Base.url_encode64 |> binary_part(0, length)
end
end

关于elixir - 如何在包含的模块中获取调用方模块名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39221484/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com