@@ -563,6 +563,13 @@ def around_save_callback
563563 end
564564 end
565565
566+ let ( :klass_with_composite_key ) do
567+ new_class do
568+ range :age , :integer
569+ field :name
570+ end
571+ end
572+
566573 let ( :klass_with_validation ) do
567574 new_class do
568575 field :name
@@ -641,6 +648,96 @@ def around_save_callback
641648 end
642649 end
643650
651+ describe 'primary key schema' do
652+ context 'simple primary key' do
653+ it 'persists a model' do
654+ klass . create_table
655+
656+ expect {
657+ described_class . execute do |txn |
658+ txn . create! klass , name : 'Alex'
659+ end
660+ } . to change ( klass , :count ) . by ( 1 )
661+ end
662+ end
663+
664+ context 'composite key' do
665+ it 'persists a model' do
666+ klass_with_composite_key . create_table
667+
668+ expect {
669+ described_class . execute do |txn |
670+ txn . create! klass_with_composite_key , name : 'Alex' , age : 3
671+ end
672+ } . to change ( klass_with_composite_key , :count ) . by ( 1 )
673+ end
674+ end
675+ end
676+
677+ describe 'primary key validation' do
678+ context 'composite key' do
679+ it 'requires sort key to be specified' do
680+ klass_with_composite_key . create_table
681+
682+ expect {
683+ described_class . execute do |txn |
684+ txn . create! klass_with_composite_key , name : 'Alex' , age : nil
685+ end
686+ } . to raise_exception ( Dynamoid ::Errors ::MissingRangeKey )
687+ end
688+ end
689+ end
690+
691+ describe 'timestamps' do
692+ before do
693+ klass . create_table
694+ end
695+
696+ it 'sets created_at and updated_at if Config.timestamps=true' , config : { timestamps : true } do
697+ travel 1 . hour do
698+ time_now = Time . now
699+
700+ obj = nil
701+ described_class . execute do |txn |
702+ obj = txn . create! klass , name : 'Alex'
703+ end
704+
705+ expect ( obj . created_at . to_i ) . to eql time_now . to_i
706+ expect ( obj . updated_at . to_i ) . to eql time_now . to_i
707+ end
708+ end
709+
710+ it 'uses provided values of created_at and updated_at if Config.timestamps=true' , config : { timestamps : true } do
711+ travel 1 . hour do
712+ created_at = updated_at = Time . now
713+
714+ obj = nil
715+ described_class . execute do |txn |
716+ obj = txn . create! klass , created_at : created_at , updated_at : updated_at
717+ end
718+
719+ expect ( obj . created_at . to_i ) . to eql created_at . to_i
720+ expect ( obj . updated_at . to_i ) . to eql updated_at . to_i
721+ end
722+ end
723+
724+ it 'does not raise error if Config.timestamps=false' , config : { timestamps : false } do
725+ expect {
726+ described_class . execute do |txn |
727+ txn . create! klass , name : 'Alex'
728+ end
729+ } . not_to raise_error
730+ end
731+
732+ it 'does not raise error if no changes and Config.timestamps=false' , config : { timestamps : false } do
733+ expect {
734+ described_class . execute do |txn |
735+ txn . create! klass , { }
736+ end
737+ } . not_to raise_error
738+ end
739+ end
740+
644741 describe 'validation' do
645742 before do
646743 klass_with_validation . create_table
@@ -729,6 +826,34 @@ def around_save_callback
729826 expect ( obj_to_save ) . to be_changed
730827 end
731828
829+ it 'rolls back the transaction when id is not unique' do
830+ existing = klass . create! ( name : 'Alex' )
831+
832+ expect {
833+ described_class . execute do |txn |
834+ txn . create! klass , name : 'Alex' , id : existing . id
835+ txn . create klass , name : 'Michael'
836+ end
837+ } . to raise_error ( Aws ::DynamoDB ::Errors ::TransactionCanceledException )
838+
839+ expect ( klass . count ) . to eql 1
840+ expect ( klass . all . to_a ) . to eql [ existing ]
841+ end
842+
843+ it 'is not marked as persisted and is marked as changed when the transaction rolled back' do
844+ obj = nil
845+
846+ expect {
847+ described_class . execute do |txn |
848+ obj = txn . create! klass , name : 'Alex'
849+ raise 'trigger rollback'
850+ end
851+ } . to raise_error ( 'trigger rollback' )
852+
853+ expect ( obj ) . not_to be_persisted
854+ expect ( obj ) . to be_changed
855+ end
856+
732857 it 'uses dumped value of partition key to create item' do
733858 klass = new_class ( partition_key : { name : :published_on , type : :date } ) do
734859 field :name
0 commit comments