我仍然是Elixir的新手并检查存储库中的一些代码,并想知道是否有办法减少以下代码片段:
def find(client) do
Common.find(client, @resource)
|> ResponseHandler.handle_response(@model_module)
end
def find(client, identifier) do
Common.find(client, @resource, identifier)
|> ResponseHandler.handle_response(@model_module)
end
def filter(client, filter) do
Common.filter(client, @resource, filter)
|> ResponseHandler.handle_response(@model_module)
end
def create(client, bank_transactions_map) do
Common.create(client, @resource, bank_transactions_map)
|> ResponseHandler.handle_response(@model_module)
end
def update(client, identifier, bank_transactions_map) do
Common.update(client, @resource, identifier, bank_transactions_map)
|> ResponseHandler.handle_response(@model_module)
end
这里的所有功能都进入相同的功能,似乎有点重复。有没有办法在模块中设置一个函数来接受一个参数并运行.handle_response行而不在每个函数中设置它?
答案 0 :(得分:2)
您可以定义一个新函数,该函数接受函数名称以及参数,并且该函数将在最后输入ResponseHandler.handle_response(@model_module)
。以下代码未经测试但应该有效:
def find(client) do
go(:find, [client, @resource])
end
def find(client, identifier) do
go(:find, [client, @resource, identifier])
end
...
def go(function, args) do
apply(Common, function, args)
|> ResponseHandler.handle_response(@model_module)
end
如果需要,您还可以自动注入@resource
作为第二个参数:
def find(client) do
go(:find, [client])
end
def find(client, identifier) do
go(:find, [client, identifier])
end
...
def go(function, [head | tail]) do
apply(Common, function, [head, @resource | tail])
|> ResponseHandler.handle_response(@model_module)
end
您可以使用宏/元编程进一步减少这一点,但如果您只有5个案例,我不推荐它,因为它使代码复杂化。我会选择第一个解决方案,因为它是最简单的解决方案。
答案 1 :(得分:1)
如果这是真正的代码,意味着函数是来自另一个具有相同名称并散布有@resource
参数列表的模块的函数的包装器,那么可以动态地定义它们:
functions =
[find: ~w|client|a,
find: ~w|client identifier|a,
filter: ~w|client filter|a,
create: ~w|client bank_transactions_map|a,
update: ~w|client identifier bank_transactions_map|a]
Enum.each(functions, fn {fun, args} ->
args = Enum.map args, &{&1, [], Elixir}
wrapped_args = with [h | t] <- args,
do: [h | [ quote(do: @resource) | t ]] # inject @resource
def unquote(fun)(unquote_splicing(args)) do
Common
|> apply(unquote(fun), unquote(wrapped_args))
|> ResponseHandler.handle_response(@model_module)
end
end)
如果包装不是那么纯粹,那么要包装的函数的初始列表应该扩展为[find: [params: [...], as: :search]
。
这种方法的优点是,一旦函数 producer 被编写并经过充分测试,添加新的包装就像更新配置文件一样简单。