我想出了以下在演员表之前调用的解决方案:
attrs = payload_fields_to_payload(attrs)
问题在于传入的attrs可以是基于原子的,但并非必须如此。那么,有没有比我在这里做的更快或更清洁的方法?我只是在属性中重命名一个键。这个任务似乎有很多代码。
def payload_fields_to_payload(attrs) do
attrs = cond do
Map.has_key?(attrs, "payload_fields") ->
Map.put(attrs, "payload", Map.get(attrs, "payload_fields"))
Map.has_key?(attrs, :payload_fields) ->
Map.put(attrs, :payload, Map.get(attrs, :payload_fields))
true -> attrs
end
attrs
end
答案 0 :(得分:1)
我只是重命名属性中的键。
这不是您的代码实际执行的操作-您的代码向地图添加了新键:
defmodule A do
def go do
attrs_list = [
%{"payload_fields" => "hello", type: "ABC"},
%{payload_fields: "goodbye", type: "XYZ"},
%{abc: "dog", xyz: "cat"}
]
Enum.map(attrs_list, fn attrs -> payload_fields_to_payload(attrs) end)
end
def payload_fields_to_payload(attrs) do
cond do
Map.has_key?(attrs, "payload_fields") ->
Map.put(attrs, "payload", Map.get(attrs, "payload_fields"))
Map.has_key?(attrs, :payload_fields) ->
Map.put(attrs, :payload, Map.get(attrs, :payload_fields))
true -> attrs
end
end
end
输出:
iex(1)> A.go | |
[ V V
%{:type => "ABC", "payload" => "hello", "payload_fields" => "hello"},
%{payload: "goodbye", payload_fields: "goodbye", type: "XYZ"},
%{abc: "dog", xyz: "cat"}
]
但是,如果旧密钥被cast()
过滤掉了,那没什么大不了的。
我将使用模式匹配和多个函数子句,而不是使用函数体内的逻辑来确定要做什么。以下解决方案将密钥payload_fields
替换为密钥payload
:
defmodule A do
def go do
attrs_list = [
%{"payload_fields" => "hello", type: "ABC"},
%{payload_fields: "goodbye", type: "XYZ"},
%{abc: "dog", xyz: "cat"}
]
Enum.map(attrs_list, fn attrs -> convert_key(attrs) end)
end
def convert_key(%{"payload_fields" => value}=map) do #string key
map
|> Map.delete("payload_fields")
|> Map.put("payload", value)
end
def convert_key(%{payload_fields: value}=map) do # atom key
map
|> Map.delete(:payload_fields)
|> Map.put(:payload, value)
end
def convert_key(map), do: map
end
输出:
iex(1)> A.go
[
%{:type => "ABC", "payload" => "hello"},
%{payload: "goodbye", type: "XYZ"},
%{abc: "dog", xyz: "cat"}
]
如果您确实要向地图添加新键(而不是重命名键),则代码可简化为:
def convert_key(%{"payload_fields" => value}=map) do
Map.put(map, "payload", value)
end
def convert_key(%{payload_fields: value}=map) do
Map.put(map, :payload, value)
end
def convert_key(map), do: map
问题是传入的attrs可以基于原子
允许这样做的问题是:如果attr映射具有1400万个原子键怎么办?繁荣!您的应用崩溃了。数百万个仅包含几个原子键的attr映射也可能发生相同的情况。这就是Phoenix为何在params
映射中使用字符串键来获取表单数据的原因-这样做是为了防止攻击者通过发送数百万个具有唯一键的请求来泛滥原子表。