Nested associations with mixed persistence

What’s the ideal way to build a form when you have two models with mixed persistence?

I have the following setup:
A User model:

schema "users"
   field :name, :string
    field :username, :string
    field :meta, :map
    field :email, :string
    has_many(:addresses, MyApp.Address)

    timestamps
  end

And an Address model:

schema "addresses" do
    field :full_name, :string
    field :address1, :string
    field :address2, :string
    field :city, :string
    field :state, :string
    field :zip, :string
    field :country, :string, length: 2

    belongs_to(:user, MyApp.User)

    timestamps
  end

During the signup flow, users are created via an oauth callback ( Twitter/Instagram ) so the I have a persisted User that I need to present a form for them to fill out an address and provide an email address.

I’ve read through http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/ but I don’t see an example of how to go about updating an attribute of a ToDoList along with adding a new ToDoItem

2 Likes

Use Ecto.Changeset.cast_assoc/3 in your User.changeset function, something like:

def changeset(model, params \\ %{}) do
  model
  |> cast(params, @allowed_fields)
  |> cast_assoc(:addresses)
end

In your controller, your changeset should include an Address like so:

changeset = User.changeset(%User{addresses: [%Address{}]})

and in your template, use inputs_for for the nested Address form.

This doesn’t give you all the details but I hope it helps.

5 Likes

Thanks @aptinio!

I also had to do this in the controller in order for the inputs_for to display in the form:

changeset = User.changeset(user) |> Ecto.Changeset.put_assoc(:addresses, [%Address{}])

3 Likes