Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Elixir / Ecto Embedded struct - updated_at not getting updated

I have an Elixir struct with an embedded struct, following the instructions from José Valim himself:

http://blog.plataformatec.com.br/2015/08/working-with-ecto-associations-and-embeds/

    defmodule MyApp.Post do
      use Ecto.Schema
    
      schema "posts" do
        field :title
        field :body
        embeds_many :comments, MyApp.Comment
        timestamps
      end
    end
    
    defmodule MyApp.Comment do
      use Ecto.Schema
    
      embedded_schema "comments" do
        field :body
        belongs_to :post, MyApp.Post
        timestamps
      end
    end

Almost everything works perfectly, with the exception of the updated_at timestamp of the embedded Comments, which seem to retain their original value after being updated.

What I mean is, if I change one of the Comments in the list and update it on the Post and save it like this:

my_post
|> change()
|> put_embed(:comments, comments)
|> Repo.update()

the update to the values works as one would expect, except the updated_at timestamp of the Comment doesn't change.

I can set it manually:

|> Map.put(:updated_at, DateTime.to_iso8601(DateTime.utc_now))

and that works, but trying to figure out why it's not being automatically set by Ecto. Using Ecto 3.5.3. Any help would be appreciated!

Migration:

defmodule MyApp.Repo.Migrations.CreatePosts do
    use Ecto.Migration

    def change do
        create table(:posts) do
            add :title, :string
            add :body, :string
            add :comments, :map
            
            timestamps()
        end
    end
end
like image 593
Seaweedsalad Avatar asked Dec 21 '20 01:12

Seaweedsalad


1 Answers

put_embed/4's behaviour is based on that of put_assoc/4, which states that:

a map or keyword list can be given to update the associated data as long as they have matching primary keys. For example, put_assoc(changeset, :comments, [%{id: 1, title: "changed"}]) will locate the comment with :id of 1 and update its title. If no comment with such id exists, one is created on the fly.

Based on the behaviour that you're commenting, I would suspect that you're not providing the :id field in the comments. This means that existing comments get deleted and the provided comments get inserted. To validate this hypothesis, check if the inserted_at or the id field changes with each execution.

like image 181
Javier García Manzano Avatar answered Oct 01 '22 06:10

Javier García Manzano