Retrieve nested value from struct

I’m wondering about the syntax to get the email value from the following conn struct:

%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...},
 assigns: %{current_user: %MyApp.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
    access_token: "17a76fa67d81e71dd826023099e33947c5d367d0614e9545b1de0391e259",
    email: "name@emailprovider.com", id: 1,...

Using “get_in” resulted in a “the Access syntax and calls to Access.get/2 are not available for the value” error.

Thanks in advance for any advice.

get_in is useful for maps, less so for structs unless they implement Access.

You can just use dot notation on structs/maps (this will raise if it does not exist on a map): conn.assigns.current_user.email

2 Likes

Perfect. Thank you for the answer and for always being so helpful around here.

2 Likes
iex(1)> conn = %Plug.Conn{}                                                     
 %Plug.Conn{adapter: {Plug.Conn, :...}, assigns: %{}, before_send: [],
 body_params: %Plug.Conn.Unfetched{aspect: :body_params},
 cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false,
 host: "www.example.com", method: "GET", owner: nil,
 params: %Plug.Conn.Unfetched{aspect: :params}, path_info: [], path_params: %{},
 peer: nil, port: 0, private: %{},
 query_params: %Plug.Conn.Unfetched{aspect: :query_params}, query_string: "",
 remote_ip: nil, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
 req_headers: [], request_path: "", resp_body: nil, resp_cookies: %{},
 resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}],
 scheme: :http, script_name: [], secret_key_base: nil, state: :unset,
 status: nil}
iex(2)> conn = Plug.Conn.assign(conn,:id,1)
 %Plug.Conn{adapter: {Plug.Conn, :...}, assigns: %{id: 1}, before_send: [],
 body_params: %Plug.Conn.Unfetched{aspect: :body_params},
 cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false,
 host: "www.example.com", method: "GET", owner: nil,
 params: %Plug.Conn.Unfetched{aspect: :params}, path_info: [], path_params: %{},
 peer: nil, port: 0, private: %{},
 query_params: %Plug.Conn.Unfetched{aspect: :query_params}, query_string: "",
 remote_ip: nil, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
 req_headers: [], request_path: "", resp_body: nil, resp_cookies: %{},
 resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}],
 scheme: :http, script_name: [], secret_key_base: nil, state: :unset,
 status: nil}
iex(3)> conn = Plug.Conn.assign(conn,:email, "name@emailprovider.com") 
 %Plug.Conn{adapter: {Plug.Conn, :...},
 assigns: %{email: "name@emailprovider.com", id: 1}, before_send: [],
 body_params: %Plug.Conn.Unfetched{aspect: :body_params},
 cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false,
 host: "www.example.com", method: "GET", owner: nil,
 params: %Plug.Conn.Unfetched{aspect: :params}, path_info: [], path_params: %{},
 peer: nil, port: 0, private: %{},
 query_params: %Plug.Conn.Unfetched{aspect: :query_params}, query_string: "",
 remote_ip: nil, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
 req_headers: [], request_path: "", resp_body: nil, resp_cookies: %{},
 resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}],
 scheme: :http, script_name: [], secret_key_base: nil, state: :unset,
 status: nil}
iex(4)> conn = Plug.Conn.assign(conn,:access_token,"17a76fa67d81e71dd826023099e33947c5d367d0614e9545b1de0391e259")
 %Plug.Conn{adapter: {Plug.Conn, :...},
 assigns: %{access_token: "17a76fa67d81e71dd826023099e33947c5d367d0614e9545b1de0391e259",
   email: "name@emailprovider.com", id: 1}, before_send: [],
 body_params: %Plug.Conn.Unfetched{aspect: :body_params},
 cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false,
 host: "www.example.com", method: "GET", owner: nil,
 params: %Plug.Conn.Unfetched{aspect: :params}, path_info: [], path_params: %{},
 peer: nil, port: 0, private: %{},
 query_params: %Plug.Conn.Unfetched{aspect: :query_params}, query_string: "",
 remote_ip: nil, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
 req_headers: [], request_path: "", resp_body: nil, resp_cookies: %{},
 resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}],
 scheme: :http, script_name: [], secret_key_base: nil, state: :unset,
 status: nil}
iex(5)> conn = Plug.Conn.assign(conn,:current_user,%{})
 %Plug.Conn{adapter: {Plug.Conn, :...},
 assigns: %{access_token: "17a76fa67d81e71dd826023099e33947c5d367d0614e9545b1de0391e259",
   current_user: %{}, email: "name@emailprovider.com", id: 1}, before_send: [],
 body_params: %Plug.Conn.Unfetched{aspect: :body_params},
 cookies: %Plug.Conn.Unfetched{aspect: :cookies}, halted: false,
 host: "www.example.com", method: "GET", owner: nil,
 params: %Plug.Conn.Unfetched{aspect: :params}, path_info: [], path_params: %{},
 peer: nil, port: 0, private: %{},
 query_params: %Plug.Conn.Unfetched{aspect: :query_params}, query_string: "",
 remote_ip: nil, req_cookies: %Plug.Conn.Unfetched{aspect: :cookies},
 req_headers: [], request_path: "", resp_body: nil, resp_cookies: %{},
 resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}],
 scheme: :http, script_name: [], secret_key_base: nil, state: :unset,
 status: nil}

.

iex(6)> conn.assigns.email 
 "name@emailprovider.com"
iex(7)> conn.assigns
 %{access_token: "17a76fa67d81e71dd826023099e33947c5d367d0614e9545b1de0391e259",
  current_user: %{}, email: "name@emailprovider.com", id: 1}
iex(8)> Map.get(conn.assigns, :email)       
 "name@emailprovider.com"
iex(9)> Kernel.get_in(conn.assigns,[:email])
 "name@emailprovider.com"
iex(10)>

Plug.Conn: Connection fields:

assigns - shared user data as a map

2 Likes

thanks. this is helpful. it’s interesting to see what the default values are too!

2 Likes