我一直在尝试使用Ecto的many_to_many字段映射来使连接表工作 - 而且可能只是我不明白预加载应该如何工作,但每当我尝试更新我的关联时(通过这样做,插入到我的连接表中),我最终得到一个空的变更集和一个新的数据库字段,两个外键都有nil。我对Phoenix和Ecto很陌生,我的谷歌搜索并没有让我走得太远,因为在Ecto中很多人都是相对较新的,并且没有很多文档。
我的模特:
defmodule SslStorage.Cert do
use SslStorage.Web, :model
alias SslStorage.User
alias SslStorage.UsersCerts
schema "certs" do
field :domain, :string
field :port, :integer
field :issuer, :string
field :expiration, :string
many_to_many :users, User, join_through: UsersCerts
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:domain, :port, :issuer, :expiration])
|> validate_required([:domain, :port, :issuer, :expiration])
end
end
defmodule SslStorage.User do
use SslStorage.Web, :model
alias SslStorage.Cert
alias SslStorage.UsersCerts
schema "users" do
field :email, :string
many_to_many :certs, Cert, join_through: UsersCerts
timestamps()
end
@doc """
Builds a changeset based on the `struct` and `params`.
"""
def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:email])
|> validate_required([:email])
end
end
defmodule SslStorage.UsersCerts do
use SslStorage.Web, :model
alias SslStorage.User
alias SslStorage.Cert
schema "users_certs" do
belongs_to :users, User
belongs_to :certs, Cert
timestamps()
end
def changeset(struct, params \\ %{}) do
struct
# my first clue something was funky:
# casting and validating user_id & cert_id kept breaking things
|> cast(params, [])
# |> validate_required([:user_id, :cert_id])
end
end
违规控制器代码(主要从Elixir ecto 2 create many_to_many association复制)
new_cert = Storage.get_or_create_cert(params)
current_user = Storage.get_or_create_user(params)
change = new_cert
|> Repo.preload(:users)
|> Cert.changeset(%{users: [current_user]})
|> Ecto.Changeset.put_assoc(:users, [current_user])
IEx.pry
change |> Repo.update!()
如果我从断点检查更改变量:
pry(6)> change
#Ecto.Changeset<action: nil,
changes: %{users: [#Ecto.Changeset<action: :update, changes: %{},
errors: [], data: #SslStorage.User<>, valid?: true>]}, errors: [],
data: #SslStorage.Cert<>, valid?: true>
pry(7)> change.data
%SslStorage.Cert{__meta__: #Ecto.Schema.Metadata<:loaded, "certs">,
domain: "spiceworks.com", expiration: "time", id: 1,
inserted_at: #Ecto.DateTime<2016-08-31 15:00:49>, issuer: "me.com",
port: 2222, updated_at: #Ecto.DateTime<2016-08-31 15:00:49>, users: []}
不知何故,关联没有按照我的预期创建,并且可以使用指导。 当然,当调用Repo.update时,我在我的数据库中使用user_id:nil和cert_id:nil获得一个新字段。
我的主要问题是:
我是否可以在尝试使用Ecto关联时完成连接表,如果是这样的话......
我做错了什么,因为我在Ecto的土地上有点迷失。