如何在凤凰中使用嵌套表单关联?

How to use Nested forms associations in phoenix?

所以我目前正在学习 Phoenix 1.3,我想学习 ecto associations。我在前端使用 Angularjs

我有两个架构 user.exprofile.ex

均由 mix phx.gen.json

生成

user.ex

schema "users" do
field(:password_hash, :string)
field(:username, :string)
# Virtual fields:
field(:password, :string, virtual: true)
field(:password_confirmation, :string, virtual: true)
# this was added
has_one(:profiles, AuthApp.Accounts.Profile)

timestamps()end

profile.ex

schema "profiles" do
field :firstname, :string
field :lastname, :string
field :photo, :string
field :user_id, :id
belongs_to :user, AuthApp.Accounts.User  # this was added

timestamps()end

配置文件控制器

def create(conn, %{"profile" => profile_params}) do
with {:ok, %Profile{} = profile} <- Accounts.create_profile(profile_params) do
  conn
  |> put_status(:created)
  |> put_resp_header("location", profile_path(conn, :show, profile))
  |> render("show.json", profile: profile)
endend

我的问题是我不知道我应该添加哪个控制器关联以及它会是什么样子。

这真的取决于你,你可以两种方式都做!但是,针对此特定场景的一些指导/最佳实践风格提示。

如果您的应用功能/页面/等主要与这些域对象之一一起工作,请使用该控制器。

例如,如果您正在呈现个人资料页面,并在其中提供各种路线,或加载各种数据以填充个人资料并启用与其相关的功能,而不是返回嵌套的 API 响应表示数据关系对于顶级配置文件有意义。

我通常会做这样的事情(从你离开的地方开始定义模式和关系): 在 ProfileController 中为我的个人资料 API 请求获取我想要的相关数据。我通常通过处理关系预加载的 Context 函数来执行此操作。在这种情况下,该组合可能类似于:

def show(conn, %{"id" => id}) do
  profile = Accounts.get_profile!(id)
  render(conn, "show.html", profile: profile)
end

假设像 Account 上下文这样的东西来保存 Profile 模式, 其中 Account.get_profile!/1 看起来像:

def get_profile!(id) do
  query =
    from(p in Account.Profile,
      where: p.user_id == ^id,
      select: p,
      preload: [:user]
    )

  YourApp.Repo.get(query)
end

这最终导致 API 响应类似于:

profile : {
  photo: {},
  user: {
    id: "1"
  }
}

从启用配置文件功能的角度来看,这很直观。

但是,有几点需要注意:

  1. 如果使用基于令牌的身份验证,我通常会通过 conn.assigns、会话和插件或某些缓存层将基本用户信息加载到应用程序中。如果有机会,Programming Phoenix 书中有这种方法的入门级示例,而 Guardian 图书馆有关于基于令牌的方法的很好信息。

  2. 如果您符合特定的 API 标准,那里会有指导方针和最佳实践,所以在谷歌搜索 "REST" 或 "GraphQL" 时X 将产生有用的见解。

  3. 我忽略了关于 authentication/authorization 等的所有内容,但是执行 (1) 的好处是您可以安全地确定 API 请求的范围,这样用户就不能请求与他们自己不同的个人资料 ID(这发生在发出基本个人资料请求并随后预加载所有用户信息时)。