ex_machina icon indicating copy to clipboard operation
ex_machina copied to clipboard

Uniq column error

Open Adzz opened this issue 4 years ago • 2 comments

I have this factory:

def thing_factory() do
  %Thing{name: Ecto.UUID.generate()}
end

name is a column with a unique index.

When I do this:

for _ <- 1..5 do
  thing = build(:thing)
  insert_list(4, :other_thing, thing: thing)
end

I get:

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

essentially saying the name is not uniq. If I change it to this it works:

for _ <- 1..5 do
  thing = insert(:thing)
  insert_list(4, :other_thing, thing: thing)
end

Am I doing something wrong?

Adzz avatar Jun 23 '20 09:06 Adzz

Hi @Adzz, I'm not a 100% sure, but I think this is what's happening.

First, I think the for comprehension is irrelevant to the problem. So think doing this will still trigger the error:

thing = build(:thing)
insert_list(4, :other_thing, thing: thing)

build(:thing) just creates a struct with the auto-generated UUID. You're then trying to insert 4 :other_thing, each of which has an associated (but not inserted) thing with the same name.

# insert :other_thing_1 (and insert :thing with auto generated UUID) => succeeds
# insert :other_thing_2 (and attempt to insert :thing with same UUID) => fails b/c that UUID is already in the database. 
# :other_thing 3 and 4 aren't even attempted

If you insert(:thing) instead of just build(:thing) to begin with, insert_list(:other_thing) will not attempt to insert thing when it's recursively inserting those 4 records.

Does that make sense? I hope this helps!

germsvel avatar Jul 17 '20 20:07 germsvel

Opened up a PR that I think fixes this issue. Let me know what you think -> https://github.com/thoughtbot/ex_machina/pull/406

germsvel avatar Dec 08 '20 11:12 germsvel