Okay, that sounds simple enough–except there’s that pesky @behaviour tag (@behavior produces a warning), and then there’s this warning:
defmodule A.B do
@behaviour Access
defstruct personal_info: %{}, other: []
def fetch(term, key), do: Map.fetch(term, key)
def get_and_update(data, key, func) do
Map.get_and_update(data, key, func)
end
def pop(data, key), do: Map.pop(data, key)
end
defmodule My do
def go do
map = %{
greeting: "hello world",
active: true,
description: "player points",
id: 118,
inserted_at: ~N[2018-08-26 19:48:22.501445],
reserved: %A.B{
personal_info: %{
game_id: "b796cbe9-0bb6-4aaf-98b0-5da81c337208",
player_id: "8ffb69ce-9a6b-44a6-8e8f-c069235d2d31",
player_name: "Lebron James"
},
other: [%{label: "Player Points", type: "text"}]
},
type: "NBA",
updated_at: ~N[2018-08-26 19:48:22.504193]
}
put_in(map, ~w{reserved personal_info player_id}a, 12345)
end
end
~/elixir_programs$ iex my.exs
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
warning: function get/3 required by behaviour Access is not implemented (in module A.B)
my.exs:1
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
Okay, even though there’s no mention of get()
anywhere in the callback section of the Access docs:
defmodule A.B do
@behaviour Access
defstruct personal_info: %{}, other: []
def fetch(term, key), do: Map.fetch(term, key)
def get_and_update(data, key, func) do
Map.get_and_update(data, key, func)
end
def pop(data, key), do: Map.pop(data, key)
def get(map, key, default), do: Map.get(map, key, default)
end
defmodule My do
def go do
map = %{
greeting: "hello world",
active: true,
description: "player points",
id: 118,
inserted_at: ~N[2018-08-26 19:48:22.501445],
reserved: %A.B{
personal_info: %{
game_id: "b796cbe9-0bb6-4aaf-98b0-5da81c337208",
player_id: "8ffb69ce-9a6b-44a6-8e8f-c069235d2d31",
player_name: "Lebron James"
},
other: [%{label: "Player Points", type: "text"}]
},
type: "NBA",
updated_at: ~N[2018-08-26 19:48:22.504193]
}
put_in(map, ~w{reserved personal_info player_id}a, 12345)
end
end
In iex:
~/elixir_programs$ iex my.exs
Erlang/OTP 20 [erts-9.3] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
Interactive Elixir (1.6.6) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> My.go
%{
active: true,
description: "player points",
greeting: "hello world",
id: 118,
inserted_at: ~N[2018-08-26 19:48:22.501445],
reserved: %A.B{
other: [%{label: "Player Points", type: "text"}],
personal_info: %{
game_id: "b796cbe9-0bb6-4aaf-98b0-5da81c337208",
player_id: 12345,
player_name: "Lebron James"
}
},
type: "NBA",
updated_at: ~N[2018-08-26 19:48:22.504193]
}
iex(2)>
Success.
So, yeah, someone needs to post a tutorial somewhere then link to it when beginners want to know how to implement Access to get at deeply nested data in a struct.
And, why shouldn’t that be as simple as:
@behaviour Access, do: Map
or:
defstruct personal_info: %{}, other: [], __delegate__: Map