Copying a struct id

Is there any way we could duplicate the id of a struct from ecto schema? I have a ecto struct with id and other fields. I am writing a function that makes a copy of the struct.

def copy_post(attrs) do
    post1 = get_post!(attrs.id)
    post1_params = Map.struct(post1)
    create_post(post1_params) do
         Post{}
         |> Post.changeset(post1_params)
         |> Repo.insert

But this still generates a new id. I would like to have the same id of post1 in my copy.

Could you show the definition of the Post.changeset function? Seems like id is not present in a list of permitted fields.

This is my ecto schema


@fields [:title]
  @required [:title]

  schema "posts" do
    field :title, :string

    timestamps()
  end

  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, @fields)
    |> unique_constraint(:title)

Try to add :id to the @fields list and retry?

I’m just guessing, but it seems to me that id is the primary key of the post table.
If this is the case, then you will get a new value for it each time you insert a record in the table; also the id value can’t be duplicated because it would violate the unique constraint the database has put on it during table creation. So you’d need a different primary key in order to have duplicated id values. But still, I’m only guessing here.

1 Like

I tried this but I get the following error


** (Ecto.ConstraintError) constraint error when attempting to insert struct:
     
         * posts_pkey (unique_constraint)

I also feel that’s the case. Do you think there is any other alternative to copy the entire struct along with the primary key? The primary key is auto-generated. I wouldn’t want to change it from auto-generated: true to autogenerated: false because I don’t generally pass an id as an attribute while creating a post. Is there any other way like modifying the copy function?

Having a duplicated primary key value is not possible, for the very nature of a primary key itself.
I feel I’m not really getting what you want to achieve, sorry :sweat_smile:

1 Like

Copy function?

def copy_post(attrs) do
    post1 = get_post!(attrs.id)
    post1_params = Map.struct(post1)
    create_post(post1_params) do
         Post{}
         |> Post.changeset(post1_params)
         |> Repo.insert

This function

@grangerelixx

I’ve been thinking… maybe you have your good reasons to duplicate records keeping tracks of their ‘original’ ids (i.e. so you can tell from which records they were copied from).

You could add a field to the posts table, let’s call it original_id, with the same datatype of id; a sort of foreign key referencing the same posts table. The copy function then would set the new record’s original_id with the id’s value of the original post been copied.

I know its not what you asked for, but it is the closest possible solution I can think of, not knowing what is the problem you want to solve. Hth.

2 Likes