Je sais qu'il est possible de créer une structure via %User{ email: '[email protected]' }
. Mais si j'avais une variable params = %{email: '[email protected]'}
existe-t-il un moyen de créer cette structure en utilisant cette variable, par exemple, %User{ params }
.
Cela donne une erreur, vous vous demandez simplement si vous pouvez l'exploser ou d'une autre manière?
Vous devez utiliser le struct/2
fonction. De la documentation:
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"}
Les réponses précédentes sont toutes les deux bonnes, avec une mise en garde: les clés de la structure sont des atomes, les clés de votre hachage peuvent être des chaînes. L'utilisation de la méthode struct () copiera uniquement les clés qui correspondent et les chaînes ne correspondront pas aux atomes. Exemple:
defmodule User do
defstruct name: "john"
end
opts = %{"name" => "meg"}
user = struct(User, opts)
#=> %User{name: "john"}
L'utilisation de la fusion est également étrange, car elle "annulera" la nature structurelle de la carte:
user = Map.merge(%User{}, opts)
#=> %{:__struct__ => User, :name => "john", "name" => "meg"}
J'ai trouvé cela sur le groupe Google elixir-lang-talk, de Jose lui-même:
https://groups.google.com/d/msg/elixir-lang-talk/6geXOLUeIpI/L9einu4EEAAJ
C'est à peu près la voie à suivre, sauf que vous pouvez tout faire en un seul passage:
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
Une autre façon de le faire en utilisant Map.merge/2
:
Exemple:
params
#=> %{email: "[email protected]"}
%User{} |> Map.merge(params)
#=> %User{ email: '[email protected]' }