CheersThankYou

CheersThankYou

Ecto Embedded Schema always register change with changeset

I have an embedded schema, and I noticed that it was always writing to the DB, even when it wasn’t updated from its default value [].

Checking with changeset, it appears to always register it as a change. Where am I going wrong with this?

You can test this in debug using the example:

defmodule Order do
  use Ecto.Schema

  schema "orders" do
    embeds_many :items, Item
  end
end

defmodule Item do
  use Ecto.Schema

  embedded_schema do
    field :title
  end
end
# create a blank changeset
order = %Order{}
orderChange = Ecto.Changeset.change(order)

orderChange |> Ecto.Changeset.put_change(:items, [])

I’ve tried this with a regular blank map, but it only appears to be occurring with an embedded_schema. I feel like I’m missing something obvious here.

Most Liked

CheersThankYou

CheersThankYou

You can replicate the code in my original example in an IEX interactive shell.

I’ve done some more playing about with it in iex and here is the process I took:

defmodule Order do
  use Ecto.Schema

  schema "orders" do
    embeds_many :items, Item, on_replace: :delete #added on_replace to allow manipulation
  end
end

defmodule Item do
  use Ecto.Schema

  embedded_schema do
    field :title
  end
end

With zero items attached to the order:

order = %Order{}
changesetWithNoItems = Ecto.Changeset.change(order)

changesetWithNoItems.data
%Order{__meta__: #Ecto.Schema.Metadata<:built, "orders">, id: nil, items: []}

# this doesn't make sens
changesetWithNoItems |> Ecto.Changeset.put_change(:items, [])
#Ecto.Changeset<
  action: nil,
  changes: %{items: []},
  errors: [],
  data: #Order<>,
  valid?: true
>

# Makes sense
changesetWithNoItems |> Ecto.Changeset.put_change(:items, nil)
#Ecto.Changeset<
  action: nil,
  changes: %{},
  errors: [items: {"is invalid", [type: {:array, :map}]}],
  data: #Order<>,
  valid?: false
>

# Makes sense 
changesetWithNoItems |> Ecto.Changeset.put_change(:items, [%Item{id: 1, title: "test"}])
#Ecto.Changeset<
  action: nil,
  changes: %{
    items: [
      #Ecto.Changeset<action: :insert, changes: %{}, errors: [], data: #Item<>,
       valid?: true>
    ]
  },
  errors: [],
  data: #Order<>,
  valid?: true
>

Then with an order that has a single item attached:


order = %Order{items: [%Item{id: 1, title: "what"}]}
changesetWithItem = Ecto.Changeset.change(order)

changesetWithItem.data 
%Order{
  __meta__: #Ecto.Schema.Metadata<:built, "orders">,
  id: nil,
  items: [%Item{id: 1, title: "what"}]
}

# Makes sense
changesetWithItem |> Ecto.Changeset.put_change(:items, [%Item{id: 1, title: "what"}])
#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #Order<>,
 valid?: true>

# Doesn't make sense
 changesetWithItem |> Ecto.Changeset.put_change(:items, [%Item{id: 1, title: "huh"}]) 
#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #Order<>,
 valid?: true>

# confirming
 (changesetWithItem |> Ecto.Changeset.put_change(:items, [%Item{id: 1, title: "huh"}])).data
%Order{
  __meta__: #Ecto.Schema.Metadata<:built, "orders">,
  id: nil,
  items: [%Item{id: 1, title: "what"}]
}

# Doesn't make sense
changesetWithItem |> Ecto.Changeset.put_change(:items, [%Item{id: 2, title: "huh"}])
#Ecto.Changeset<
  action: nil,
  changes: %{
    items: [
      #Ecto.Changeset<action: :replace, changes: %{}, errors: [], data: #Item<>,
       valid?: true>,
      #Ecto.Changeset<action: :insert, changes: %{}, errors: [], data: #Item<>,
       valid?: true>
    ]
  },
  errors: [],
  data: #Order<>,
  valid?: true
>

# Confirming
((changesetWithItem |> Ecto.Changeset.put_change(:items, [%Item{id: 1, title: "huh"}, %Item{id: 2, title: "something new"}])).changes.items |> hd).data
%Item{id: 1, title: "huh"}

Where Next?

Popular in Questions Top

lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
Werner
Hi, I’m using Ubuntu 18.04 and after updating to OTP-24.0 yesterday i have this warning when I run “mix local.hex”: 14:57:30.512 [warn] ...
New
Kagamiiiii
Student &amp; New to elixir. Nice language. I want to convert a english character, e.g. “a”, which is stored in a variable, to it’s asci...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
beno
I will often find my self writing things similar to: case some_value do nil -&gt; something() "" -&gt; something() _ -&gt; someth...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
srinivasu
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 27727 240
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New

We're in Beta

About us Mission Statement