@@ -419,4 +419,89 @@ defmodule AshPostgres.AtomicsTest do
419419 end
420420 end
421421 )
422+
423+ describe "atomic create (create_atomics)" do
424+ # Tests for atomic_set on create actions - supported in Ash 3.14+
425+
426+ test "atomic_set works on create with fragment subquery" do
427+ # Create 3 initial posts
428+ Enum . each ( 1 .. 3 , fn i ->
429+ Post
430+ |> Ash.Changeset . for_create ( :create , % { title: "post_#{ i } " , price: i } )
431+ |> Ash . create! ( )
432+ end )
433+
434+ # Use atomic_set to set score to count of existing posts
435+ post =
436+ Post
437+ |> Ash.Changeset . for_create ( :create , % { title: "new_post" , price: 10 } )
438+ |> Ash.Changeset . atomic_set (
439+ :score ,
440+ expr ( fragment ( "(SELECT count(*) FROM posts WHERE type = 'sponsored')" ) )
441+ )
442+ |> Ash . create! ( )
443+
444+ # Score should be 3 (count of existing sponsored posts when INSERT ran)
445+ assert post . score == 3
446+ end
447+
448+ test "atomic_set works on create with simple literal expression" do
449+ post =
450+ Post
451+ |> Ash.Changeset . for_create ( :create , % { title: "test" , price: 5 } )
452+ |> Ash.Changeset . atomic_set ( :score , expr ( 42 ) )
453+ |> Ash . create! ( )
454+
455+ assert post . score == 42
456+ end
457+
458+ test "atomic_set works on create with arithmetic expression" do
459+ post =
460+ Post
461+ |> Ash.Changeset . for_create ( :create , % { title: "test" , price: 10 } )
462+ |> Ash.Changeset . atomic_set ( :score , expr ( 5 + 15 ) )
463+ |> Ash . create! ( )
464+
465+ assert post . score == 20
466+ end
467+
468+ test "atomic_set on create overrides attributes when both are set" do
469+ # If both attributes and atomic_set set a value, atomics should win
470+ post =
471+ Post
472+ |> Ash.Changeset . for_create ( :create , % { title: "test" , price: 5 , score: 999 } )
473+ |> Ash.Changeset . atomic_set ( :score , expr ( 100 ) )
474+ |> Ash . create! ( )
475+
476+ # The atomic expression should override the attribute value
477+ assert post . score == 100
478+ end
479+
480+ test "atomic_set on create works sequentially" do
481+ # Create 2 initial posts
482+ Enum . each ( 1 .. 2 , fn i ->
483+ Post
484+ |> Ash.Changeset . for_create ( :create , % { title: "initial_#{ i } " , price: i } )
485+ |> Ash . create! ( )
486+ end )
487+
488+ # Create posts one by one with atomic_set
489+ results =
490+ Enum . map ( 1 .. 3 , fn i ->
491+ Post
492+ |> Ash.Changeset . for_create ( :create , % { title: "new_#{ i } " , price: i } )
493+ |> Ash.Changeset . atomic_set (
494+ :score ,
495+ expr ( fragment ( "(SELECT count(*) FROM posts WHERE type = 'sponsored')" ) )
496+ )
497+ |> Ash . create! ( )
498+ end )
499+
500+ # First post sees 2 existing posts
501+ assert Enum . at ( results , 0 ) . score == 2
502+ # Subsequent posts see incrementing counts
503+ assert Enum . at ( results , 1 ) . score == 3
504+ assert Enum . at ( results , 2 ) . score == 4
505+ end
506+ end
422507end
0 commit comments