插头连接或会话中的 KeyError
KeyError in Plug connection or session
所以我收到以下错误,因为我试图访问 :id
密钥。这里不足为奇。但是,我的实际问题是为什么将用户放在 :session
键内?这个插件是特定的吗?我不记得将用户设置为密钥 :session
,如下面的视图所示。
错误:
** (KeyError) key :id not found in:
%{
session: %ExampleApp.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
email: "ka@example.com",
first_name: "keith",
id: 356,
inserted_at: #Ecto.DateTime<2016-08-25 00:56:51>,
last_name: "a.",
updated_at: #Ecto.DateTime<2016-08-25 00:56:51>,
username: "keith"
},
view_module: ExampleApp.SessionView,
view_template: "show.json"
}
导致错误的视图:
defmodule ExampleApp.SessionView do
use ExampleApp.Web, :view
def render("show.json", %{jwt: jwt, user: user, exp: exp}) do
%{
jwt: jwt,
exp: exp,
user: render_one(user, __MODULE__, "show.json")
}
end
def render("show.json", user) do
%{
id: user.id, #<------------------------------------------ HERE
username: user.username,
last_name: user.last_name,
first_name: user.first_name
}
end
我必须执行以下操作才能访问用户信息:
...
def render("show.json", user) do
%{
id: user.session.id, #<------------------------------------------ HERE
username: user.session.username,
last_name: user.session.last_name,
first_name: user.session.first_name
}
end
如果有帮助,请看控制器:
defmodule ExampleApp.RegistrationController do
use ExampleApp.Web, :controller
alias ExampleApp.{Repo, User, SessionView}
def create(conn, %{"user" => user_params}) do
changeset = User.new_changeset(%User{}, user_params)
case Repo.insert(changeset) do
{:ok, user} ->
{:ok, jwt, claims} = user |> Guardian.encode_and_sign(:token)
exp = Map.get(claims, "exp")
conn
|> put_status(:created)
|> render(SessionView, "show.json", %{jwt: jwt, user: user, exp: exp})
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render("error.json", changeset: changeset)
end
end
end
我在这里做错了什么?预先感谢您的帮助。
However, my actual question is why is the user placed inside the :session
key?
那是因为 render_one
尝试使用您传递的视图名称来猜测键名。在本例中,您传递了 SessionView
,因此推断用于模型的密钥是 :session
。如果您希望它位于 :user
中,您可以传递 as: :user
:
def render("show.json", %{jwt: jwt, user: user, exp: exp}) do
%{
jwt: jwt,
exp: exp,
user: render_one(user, __MODULE__, "show.json", as: :user)
}
end
您可以在 documentation for Phoenix.View.render_one/4 中阅读更多相关信息。
...
render_one user, UserView, "show.html"
...
The underlying user is passed to the view and template as :user
, which is inflected from the view name. The name of the key in assigns can be customized with the :as
option:
render_one user, UserView, "show.html", as: :data
...
所以我收到以下错误,因为我试图访问 :id
密钥。这里不足为奇。但是,我的实际问题是为什么将用户放在 :session
键内?这个插件是特定的吗?我不记得将用户设置为密钥 :session
,如下面的视图所示。
错误:
** (KeyError) key :id not found in:
%{
session: %ExampleApp.User{
__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
email: "ka@example.com",
first_name: "keith",
id: 356,
inserted_at: #Ecto.DateTime<2016-08-25 00:56:51>,
last_name: "a.",
updated_at: #Ecto.DateTime<2016-08-25 00:56:51>,
username: "keith"
},
view_module: ExampleApp.SessionView,
view_template: "show.json"
}
导致错误的视图:
defmodule ExampleApp.SessionView do
use ExampleApp.Web, :view
def render("show.json", %{jwt: jwt, user: user, exp: exp}) do
%{
jwt: jwt,
exp: exp,
user: render_one(user, __MODULE__, "show.json")
}
end
def render("show.json", user) do
%{
id: user.id, #<------------------------------------------ HERE
username: user.username,
last_name: user.last_name,
first_name: user.first_name
}
end
我必须执行以下操作才能访问用户信息:
...
def render("show.json", user) do
%{
id: user.session.id, #<------------------------------------------ HERE
username: user.session.username,
last_name: user.session.last_name,
first_name: user.session.first_name
}
end
如果有帮助,请看控制器:
defmodule ExampleApp.RegistrationController do
use ExampleApp.Web, :controller
alias ExampleApp.{Repo, User, SessionView}
def create(conn, %{"user" => user_params}) do
changeset = User.new_changeset(%User{}, user_params)
case Repo.insert(changeset) do
{:ok, user} ->
{:ok, jwt, claims} = user |> Guardian.encode_and_sign(:token)
exp = Map.get(claims, "exp")
conn
|> put_status(:created)
|> render(SessionView, "show.json", %{jwt: jwt, user: user, exp: exp})
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render("error.json", changeset: changeset)
end
end
end
我在这里做错了什么?预先感谢您的帮助。
However, my actual question is why is the user placed inside the
:session
key?
那是因为 render_one
尝试使用您传递的视图名称来猜测键名。在本例中,您传递了 SessionView
,因此推断用于模型的密钥是 :session
。如果您希望它位于 :user
中,您可以传递 as: :user
:
def render("show.json", %{jwt: jwt, user: user, exp: exp}) do
%{
jwt: jwt,
exp: exp,
user: render_one(user, __MODULE__, "show.json", as: :user)
}
end
您可以在 documentation for Phoenix.View.render_one/4 中阅读更多相关信息。
...
render_one user, UserView, "show.html"
...
The underlying user is passed to the view and template as
:user
, which is inflected from the view name. The name of the key in assigns can be customized with the:as
option:render_one user, UserView, "show.html", as: :data
...