Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Optimistic locking is the way to go, but as you might have noticed already, your code will never raise ActiveRecord::StaleObjectError, since child object creation in has_many association skips the locking mechanism. Take a look at the following SQL:</p> <pre><code>UPDATE `scheduled_runs` SET `lock_version` = COALESCE(`lock_version`, 0) + 1, `attendances_count` = COALESCE(`attendances_count`, 0) + 1 WHERE (`id` = 113338481) </code></pre> <p>When you update attributes in the <strong>parent</strong> object, you usually see the following SQL instead:</p> <pre><code>UPDATE `scheduled_runs` SET `updated_at` = '2010-07-23 10:44:19', `lock_version` = 2 WHERE id = 113338481 AND `lock_version` = 1 </code></pre> <p>The above statement shows how optimistic locking is implemented: Notice the <code>lock_version = 1</code> in WHERE clause. When race condition happens, concurrent processes try to run this exact query, but only the first one succeeds, because the first one atomically updates the lock_version to 2, and subsequent processes will fail to <strong>find</strong> the record and raise ActiveRecord::StaleObjectError, since the same record doesn't have <code>lock_version = 1</code> any longer.</p> <p>So, in your case, a possible workaround is to touch the parent right before you create/destroy a child object, like so:</p> <pre><code>def attend(user) self.touch # Assuming you have updated_at column attendance = self.attendances.create(:user_id =&gt; user.id) rescue ActiveRecord::StaleObjectError #...do something... end </code></pre> <p>It's not meant to strictly avoid race conditions, but practically it should work in most cases.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload