Ecto many_to_many关联不会编辑变更集

时间:2016-08-31 16:38:54

标签: postgresql elixir phoenix-framework ecto

我一直在尝试使用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获得一个新字段。

我的主要问题是:

  1. 我是否可以在尝试使用Ecto关联时完成连接表,如果是这样的话......

  2. 我做错了什么,因为我在Ecto的土地上有点迷失。

0 个答案:

没有答案