@@ -1064,10 +1064,142 @@ resolving the fields with a second query against the table since a query
10641064against GSI then a query on base table is still likely faster than scan
10651065on the base table*
10661066
1067- ### Transaction Writes
1067+ ### Transactions in Dynamoid
10681068
1069- Multiple write actions can be grouped together and submitted as an all-or-nothing operation.
1070- See the [ transation documentation] ( README_transact.md ) .
1069+ > [ !WARNING]
1070+ > Please note that this API is experimental and can be changed in
1071+ > future releases.
1072+
1073+ Multiple modifying actions can be grouped together and submitted as an
1074+ all-or-nothing operation. Atomic modifying operations are supported in
1075+ Dynamoid using transactions. If any action in the transaction fails they
1076+ all fail.
1077+
1078+ The following actions are supported:
1079+
1080+ * ` #create ` /` #create! ` - add a new model if it does not already exist
1081+ * ` #save ` /` #save! ` - create or update model
1082+ * ` #update_attributes ` /` #update_attributes! ` - modifies one or more attributes from an existig
1083+ model
1084+ * ` #delete ` - remove an model without callbacks nor validations
1085+ * ` #destroy ` /` #destroy! ` - remove an model
1086+ * ` #upsert ` - add a new model or update an existing one, no callbacks
1087+ * ` #update_fields ` - update a model without its instantiation
1088+
1089+ These methods are supposed to behave exactly like their
1090+ non-transactional counterparts.
1091+
1092+
1093+ #### Create models
1094+
1095+ Models can be created inside of a transaction. The partition and sort
1096+ keys, if applicable, are used to determine uniqueness. Creating will
1097+ fail with ` Aws::DynamoDB::Errors::TransactionCanceledException ` if a
1098+ model already exists.
1099+
1100+ This example creates a user with a unique id and unique email address by
1101+ creating 2 models. An additional model is upserted in the same
1102+ transaction. Upsert will update ` updated_at ` but will not create
1103+ ` created_at ` .
1104+
1105+ ``` ruby
1106+ user_id = SecureRandom .uuid
1107+ 1108+
1109+ Dynamoid ::TransactionWrite .execute do |txn |
1110+ txn.create(User , id: user_id)
1111+ txn.create(UserEmail , id: " UserEmail##{ email } " , user_id: user_id)
1112+ txn.create(Address , id: ' A#2' , street: ' 456' )
1113+ txn.upsert(Address , ' A#1' , street: ' 123' )
1114+ end
1115+ ```
1116+
1117+ #### Save models
1118+
1119+ Models can be saved in a transaction. New records are created otherwise
1120+ the model is updated. Save, create, update, validate and destroy
1121+ callbacks are called around the transaction as appropriate. Validation
1122+ failures will throw ` Dynamoid::Errors::DocumentNotValid ` .
1123+
1124+ ``` ruby
1125+ user = User .find(1 )
1126+ article = Article .new (body: ' New article text' , user_id: user.id)
1127+
1128+ Dynamoid ::TransactionWrite .execute do |txn |
1129+ txn.save(article)
1130+
1131+ user.last_article_id = article.id
1132+ txn.save(user)
1133+ end
1134+ ```
1135+
1136+ #### Update models
1137+
1138+ A model can be updated by providing a model or primary key, and the fields to update.
1139+
1140+ ``` ruby
1141+ Dynamoid ::TransactionWrite .execute do |txn |
1142+ # change name and title for a user
1143+ txn.update_attributes(user, name: ' bob' , title: ' mister' )
1144+
1145+ # sets the name and title for a user
1146+ # The user is found by id (that equals 1)
1147+ txn.update_fields(User , ' 1' , name: ' bob' , title: ' mister' )
1148+ end
1149+ ```
1150+
1151+ #### Destroy or delete models
1152+
1153+ Models can be used or the model class and key can be specified.
1154+ ` #destroy ` uses callbacks and validations. Use ` #delete ` to skip
1155+ callbacks and validations.
1156+
1157+ ``` ruby
1158+ article = Article .find(' 1' )
1159+ tag = article.tag
1160+
1161+ Dynamoid ::TransactionWrite .execute do |txn |
1162+ txn.destroy(article)
1163+ txn.delete(tag)
1164+
1165+ txn.delete(Tag , ' 2' ) # delete record with hash key '2' if it exists
1166+ txn.delete(Tag , ' key#abcd' , ' range#1' ) # when sort key is required
1167+ end
1168+ ```
1169+
1170+ #### Validation failures that don't raise
1171+
1172+ All of the transaction methods can be called without the ` ! ` which
1173+ results in ` false ` instead of a raised exception when validation fails.
1174+ Ignoring validation failures can lead to confusion or bugs so always
1175+ check return status when not using a method with ` ! ` .
1176+
1177+ ``` ruby
1178+ user = User .find(' 1' )
1179+ user.red = true
1180+
1181+ Dynamoid ::TransactionWrite .execute do |txn |
1182+ if txn.save(user) # won't raise validation exception
1183+ txn.update_fields(UserCount , user.id, count: 5 )
1184+ else
1185+ puts ' ALERT: user not valid, skipping'
1186+ end
1187+ end
1188+ ```
1189+
1190+ #### Incrementally building a transaction
1191+
1192+ Transactions can also be built without a block.
1193+
1194+ ``` ruby
1195+ transaction = Dynamoid ::TransactionWrite .new
1196+
1197+ transaction.create(User , id: user_id)
1198+ transaction.create(UserEmail , id: " UserEmail##{ email } " , user_id: user_id)
1199+ transaction.upsert(Address , ' A#1' , street: ' 123' )
1200+
1201+ transaction.commit # changes are persisted in this moment
1202+ ```
10711203
10721204### PartiQL
10731205
0 commit comments