lenguaje - En Elixir, ¿cómo se inicializa una estructura con una variable de mapa?
phoenix framework español (3)
Sé que es posible crear una estructura a través de
%User{ email: ''[email protected]'' }
.
Pero si tuviera una variable
params = %{email: ''[email protected]''}
hay una manera de crear esa estructura usando esa variable, por ejemplo,
%User{ params }
.
Esto da un error, ¿solo se pregunta si puede explotarlo o de alguna otra manera?
Debe usar la función
struct/2
.
De los documentos:
defmodule User do
defstruct name: "john"
end
struct(User)
#=> %User{name: "john"}
opts = [name: "meg"]
user = struct(User, opts)
#=> %User{name: "meg"}
struct(user, unknown: "value")
#=> %User{name: "meg"}
Las respuestas anteriores son buenas, con una advertencia: las claves en la estructura son átomos, las claves en su hash pueden ser cadenas. El uso del método struct () solo copiará sobre las claves que coinciden, y las cadenas no coincidirán con los átomos. Ejemplo:
defmodule User do
defstruct name: "john"
end
opts = %{"name" => "meg"}
user = struct(User, opts)
#=> %User{name: "john"}
Usar fusión también es extraño, porque "deshacerá" la naturaleza de estructura del Mapa:
user = Map.merge(%User{}, opts)
#=> %{:__struct__ => User, :name => "john", "name" => "meg"}
Encontré esto en el Grupo de Google elixir-lang-talk, del propio José:
https://groups.google.com/d/msg/elixir-lang-talk/6geXOLUeIpI/L9einu4EEAAJ
Ese es prácticamente el camino a seguir, excepto que puede hacer todo en una sola pasada:
def to_struct(kind, attrs) do struct = struct(kind) Enum.reduce Map.to_list(struct), struct, fn {k, _}, acc -> case Map.fetch(attrs, Atom.to_string(k)) do {:ok, v} -> %{acc | k => v} :error -> acc end end end
Otra forma de hacerlo usando
Map.merge/2
:
Ejemplo:
params
#=> %{email: "[email protected]"}
%User{} |> Map.merge(params)
#=> %User{ email: ''[email protected]'' }