Ecto: handling deeply nested associations in embedded_schema
Asked Answered
P

1

6

I'm working on the complex registration form. My users will have their profiles with contact info and collections of items. My schemas (User, Profile, Phones, Collections, Items) look like this:

defmodule MyProject.User

  schema "users" do
    field :email, :string
    field :name, :string
    has_many :profiles, MyProject.Profile, on_delete: :delete_all
    has_many :collections, through: [:profiles, :collections]
    timestamps()    
  end
end

defmodule MyProject.Profile

  schema "profiles" do
    field :address, :string
    field :skype, :string
    belongs_to :user, MyProject.User
    has_many :phones, MyProject.Phone, on_delete: :delete_all
    has_many :collections, MyProject.Collection, on_delete: :delete_all
    timestamps()    
  end
end  

defmodule MyProject.Phone

  schema "phones" do
    field :phone, :string
    belongs_to :profile, MyProject.Profile
  end
end

defmodule MyProject.Collection

  schema "collections" do
    field :name, :string
    has_many :items, MyProject.Item, on_delete: :delete_all
    timestamps()    
  end
end

defmodule MyProject.Item

  schema "items" do
    field :name, :string
    field :type, :string
    field :url, :string
    belongs_to :collection, MyProject.Collection
    timestamps()    
  end
end 

Now I need to build complex registration form which allows to create user and his profile with some phones and one collection with some items in it all at once, with one form submit. As the table registration doesn't exist I thought that I need to use embedded_schema for this, as it's not tied to the database table:

defmodule MyProject.Registration

  embedded_schema do

  end
end

But I'm not sure how to describe all nested associations inside of it. Should I use has_one, has_many or embed_one, embed_many or neither of them, what are the implications? How to structure the form, should I use inputs_for for the nested associations? How to save all associated values to the database to preserve all relationships? First, the User needs to be saved, then his Profile, then some Phones, then the Collection and finally some Items. And all these should be tied together.

Papaya answered 25/6, 2017 at 9:7 Comment(0)
G
0

I know this question is ancient but it always comes up in my searches.

Not overly satisfying but the best answer is, it depends. embeds_one/embeds_many won't keep track of the same record because they don't have the on_replace: :update option. This means that if you are running the changeset multiple times (for example in a LiveView each time the user adds new input) your changeset will loose track of what the original record was.

For that reason I'd recommend using has_one/has_many because it's easier to keep track of the original records.

From there I'd look into using a Multi operation to get specific data from your embedded schema and converting it into records to persist to the database.

Gouty answered 24/10, 2023 at 20:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.