Подтвердить что ты не робот

В Elixir, как вы инициализируете структуру с помощью переменной карты

Я знаю, что можно создать структуру через %User{ email: '[email protected]' }. Но если бы у меня была переменная params = %{email: '[email protected]'}, то был бы способ создать эту структуру, используя эту переменную, например, %User{ params }.

Это дает ошибку, просто интересно, можете ли вы взорвать ее или каким-либо другим способом?

4b9b3361

Ответ 1

Вы должны использовать функцию struct/2. Из документов:

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"}

Ответ 2

Предыдущие ответы оба хороши, с одной оговоркой: ключи в структуре являются атомами, ключи в вашем хеше могут быть строками. Использование метода struct() будет копировать только по ключам, которые соответствуют, и строки не будут соответствовать атомам. Пример:

defmodule User do
  defstruct name: "john"
end

opts = %{"name" => "meg"}
user = struct(User, opts)
#=> %User{name: "john"}

Использование слияния также нечетно, потому что оно "отменит" структуру структуры Карты:

user = Map.merge(%User{}, opts)
#=> %{:__struct__ => User, :name => "john", "name" => "meg"}

Нашел это в группе Google elixir-lang-talk от самого Хосе:

https://groups.google.com/d/msg/elixir-lang-talk/6geXOLUeIpI/L9einu4EEAAJ

Это в значительной степени способ, за исключением того, что вы можете сделать все за один проход:

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