Many to Many Changeset failing

Hey folks, I’m clearly doing something wrong, but I’m having a hard time finding it.

I expect companies to contain a map of “Company” records inside the list of changes, but it’s empty. What am I doing wrong?

Maybe try (attrs[:companies] || attrs["companies"] || "") instead of (attrs["companies"] || "").

Sorry for off-topic, but I wouldn’t insert data (get_or_insert_company) to database inside changeset functions, as it makes testing and probably some other things more involved. I would do it with a multi in your case.

In general, it’s a good idea to separate “pure” and “non-pure” code, I think …

I would also probably rewrite your changeset like this

  def changeset(domain, attrs) do
    domain
    |> cast(attrs, [:domain_name, :companies])
    |> validate_required([:domain_name])
    |> put_companies()
  end

  @spec put_companies(Ecto.Changeset.t) :: Ecto.Changeset.t
  defp put_companies(%{valid?: true, changes: %{companies: companies}} = changeset) do
    companies = 
      companies
      |> String.split(",")
      |> Stream.map(&String.trim/1)
      |> Enum.reject(&(&1 == ""))
    put_change(changeset, :companies, companies) # or something like that
  end
  defp put_companies(changeset), do: changeset

or maybe just use a multi, don;t know.

1 Like

Are the companies getting inserted successfully?

This is a bit of a shot in the dark, but are you using Phoenix 1.3? If you have a context created around companies I would try inserting using the methods provided there (something like Context.create_company). I don’t believe Repo is available by default in those files. You would need to use AppName.Repo to access it directly. Though, I believe it should be throwing an error instead of returning a changeset if that were the case so I could be wrong.

This was exactly the issue I was having. A bit of play with IEx.pry proved it out. Thanks!

You’re right, this is a much better way to rewrite things, ultimately that’s what I was trying to do, but still thinking about it in a more linear way. “Oh naturally I have to call Repo to add some stuff”. (Also, attempting to borrow samples from all over the “What’s New in Ecto” doc.) writing it this way, avoids the next issue I immediately ran into, which @DIW mentioned:

Thanks for the insight from you both.