Search code examples
phoenix-frameworkecto

Change a changeset


I don't understand how I can change the values of a given changeset.

Setup

mix phoenix.new shop
cd shop
mix ecto.create
mix phoenix.gen.html Product products name price:integer
mix ecto.migrate

web/router.ex

[...]
scope "/", Shop do
  pipe_through :browser # Use the default browser stack

  get "/", PageController, :index
  resources "/products", ProductController
end
[...]

The Problem

I start the IEX and create a new changeset:

iex -S mix phoenix.server
iex(1)> alias Shop.Product
iex(2)> changeset = Product.changeset(%Product{price: 1})
#Ecto.Changeset<action: nil, changes: %{},
 errors: [name: {"can't be blank", [validation: :required]}],
 data: #Shop.Product<>, valid?: false>

How can I change that given changeset now? The following code doesn't work:

iex(3)> changeset = Product.changeset(changeset, %{name: "Orange"})
#Ecto.Changeset<action: nil, changes: %{name: "Orange"},
 errors: [name: {"can't be blank", [validation: :required]}],
 data: #Shop.Product<>, valid?: false>

Because of the errors I can't do a Shop.Repo.insert(changeset) now.

I know that in this specific example I could change the iex(2) line to get the changeset I want. But I'd like to know how to manipulate a changeset after it's been created.


Solution

  • Product.changeset(changeset.data, Map.merge(changeset.changes, %{name: "Orange"})) does the trick. Thanks to Dogbert.

    $ iex -S mix phoenix.server
    iex(1)> alias Shop.Product
    Shop.Product
    iex(2)> changeset = Product.changeset(%Product{price: 1})
    #Ecto.Changeset<action: nil, changes: %{},
     errors: [name: {"can't be blank", [validation: :required]}],
     data: #Shop.Product<>, valid?: false>
    iex(3)> changeset = Product.changeset(changeset.data, Map.merge(changeset.changes, %{name: "Orange"}))
    #Ecto.Changeset<action: nil, changes: %{name: "Orange"}, errors: [],
     data: #Shop.Product<>, valid?: true>
    iex(4)>