diff options
author | Joe Van Dyk <joe@tanga.com> | 2015-03-21 01:16:13 -0700 |
---|---|---|
committer | Joe Van Dyk <joe@tanga.com> | 2015-03-21 01:16:13 -0700 |
commit | 4364211b7731f7b99b18c31456138c2e0f0c2aef (patch) | |
tree | 152ebf1c08c65d9767012ec1f361f5a871fbec1e /activerecord | |
parent | 92a3c8dcdf174dab5e8759031b6bbe6cd891fe3c (diff) | |
download | rails-4364211b7731f7b99b18c31456138c2e0f0c2aef.tar.gz rails-4364211b7731f7b99b18c31456138c2e0f0c2aef.tar.bz2 rails-4364211b7731f7b99b18c31456138c2e0f0c2aef.zip |
Fix documentation for find_or_create_by
The code in the comment fails on concurrent inserts if done inside a transaction.
The fix is to force a savepoint to run so that if the database raises an unique violation exception. Otherwise, you'll get errors like:
```
(0.3ms) BEGIN
Cart Load (0.5ms) SELECT "carts".* FROM "carts" WHERE "carts"."uuid" = '12345' LIMIT 1
# Another process inserts a cart with uuid of '12345' right now
SQL (4371.7ms) INSERT INTO "carts" ("created_at", "updated_at", "uuid") VALUES ('2015-03-21 01:05:07.833231', '2015-03-21 01:05:07.833231', '12345') RETURNING "id" [["created_at", Sat, 21 Mar 2015 01:05:07 PDT -07:00], ["updated_at", Sat, 21 Mar 2015 01:05:07 PDT -07:00], ["uuid", "12345"]]
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "carts_uuid_idx1"
DETAIL: Key (uuid)=(12345) already exists.
: INSERT INTO "carts" ("created_at", "updated_at", "uuid") VALUES ('2015-03-21 01:05:07.833231', '2015-03-21 01:05:07.833231', '12345') RETURNING "id"
# Retrying the find
Cart Load (0.8ms) SELECT "carts".* FROM "carts" WHERE "carts"."uuid" = '12345' LIMIT 1
PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
: SELECT "carts".* FROM "carts" WHERE "carts"."uuid" = '12345' LIMIT 1
(0.1ms) ROLLBACK
ActiveRecord::StatementInvalid: PG::InFailedSqlTransaction: ERROR: current transaction is aborted, commands ignored until end of transaction block
: SELECT "carts".* FROM "carts" WHERE "carts"."uuid" = '12345' LIMIT 1
```
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/relation.rb | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 6bbec7c0c0..85648a7f8f 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -205,7 +205,9 @@ module ActiveRecord # constraint an exception may be raised, just retry: # # begin - # CreditAccount.find_or_create_by(user_id: user.id) + # CreditAccount.transaction(requires_new: true) do + # CreditAccount.find_or_create_by(user_id: user.id) + # end # rescue ActiveRecord::RecordNotUnique # retry # end |