# Session Based Record Locking - Solutions?

**URL:** <https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137>\
**Category:** Rails\
**Created:** [February 24, 2006, 12:36am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137 "2006-02-24T00:36:08Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 12:36am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/1 "2006-02-24T00:36:08Z")

</div>

All,

I’ve written a simple job/opportunity tracking database app via RoR.

I have about 10 internal users.

Sometimes 2 people will want to update the same record at more or less  
the same time and they collide.

In particular user 1 may edit a record, then get distracted, and  
finally an hour later they click save.

During that hour user 2 may have pulled up the record, edited it, and  
saved it. The later save by user 1 undoes user 2’s changes.

I can’t think of any web technology that would help with this but …

I’m hoping that a session lock could somehow be used. Maybe a  
background Java Script app or something could somehow keep a session  
lock instantiated and if the browser is killed the seesion lock is  
released?

Ideas welcome.

## Thanks Greg

Greg F.  
The Norcross Group  
Forensics for the 21st Century

---

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 12:45am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/2 "2006-02-24T00:45:16Z")

</div>

Hi Greg,

In a similar situation I have simply used the ActiveRecord::Locking  
module by adding a lock\_version column to the table(s) in question and  
handling the ActiveRecord::StaleObjectError if/when it is thrown. It’s  
pretty simple really and will probalby be a lot easier to implment  
than a global application mutex.

Anyway, HTH,  
Dan.

---

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 12:54am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/3 "2006-02-24T00:54:20Z")

</div>

Greg,

I don’t really have something to add having read Dan’s response –  
looks like ActiveRecord already includes the approach I was going to  
suggest. In case you weren’t aware of this kind of system,  
essentially it involves keeping a timestamp with the record that is  
updated everytime the record is. Then, when performing an update, the  
system checks whether the timestamp on record matches the one that  
the updater has – if not there’s been an update already and you’ll  
need to handle it.

If you wanted to you could perhaps have something poll every 10  
seconds or so (and on saving of course), then update where necessary.  
Perhaps warn the user, update fields that haven’t changed, that kinda  
thing.

Regards,  
Paul

---

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 1:06am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/4 "2006-02-24T01:06:29Z")

</div>

Greg,

I’ve only been using Ruby and Rails for a relatively short while, but  
I believe what ActiveRecord does depends on how you call it’s methods.

I believe you’ll have to do something like

record = Record.find\_by\_id(1)  
record.save!

Suffixing it with an exclamation mark should cause an error to be  
raised should it fail.

Is that what you mean? Incidentally, it should be relatively trivial  
to put together a unit test for this, probably a good way to go –  
verify assumptions on how ActiveRecord deals with this stuff.

Regards,  
Paul

---

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 1:03am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/5 "2006-02-24T01:03:27Z")

</div>

On 2/23/06, Dan S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hi Greg,
> 
> In a similar situation I have simply used the ActiveRecord::Locking  
> module by adding a lock\_version column to the table(s) in question and  
> handling the ActiveRecord::StaleObjectError if/when it is thrown. It’s  
> pretty simple really and will probalby be a lot easier to implment  
> than a global application mutex.
> 
> Anyway, HTH,  
> Dan.

To get an failed update (with error message?) should I have to do  
anything besides have a lock\_version field? Should it work in devel  
mode?

I ask because I already have a lock\_version field in my table.

In my dev instance I just tried:

user 1: edit record, edit comment to say “Should Fail”  
user 2: edit record, edit comment to say “Should Succeed”  
user 2: click save, comment says “Should Succeed”  
user 1: click save, comment says “Should Fail”

Obviously this is not what you described. For my 2 users I was using  
a single client, but one was firefox and one was IE. I assume that  
should qualify as seperate users.

Thanks  
Greg

---

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 1:15am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/6 "2006-02-24T01:15:35Z")

</div>

Ack, that’s probably because on the post of the User1 comment, the  
model is being reloaded, so it gets the new lock version number which  
it then happily increments. By default, this will only stop the case  
when 2 people press save at the same instant and the following  
happens:

1. user1 loads modelA (lock version 0)
2. user2 loads modelA (lock version 0)
3. users 1&2 change data as they need to within their own models
4. user1 saves modelA to table (incrementing lock version to 1)
5. user2 saves modelA but lock version of model (0) does not match  
that in table (1) so exception is thrown.

A little but more work will be needed by the looks for you… Basically  
you will need to get out the lock\_version and pass it as a param to  
your post, so that on the receiving action you can get the  
lock\_version from the DB before you update and compare to you posted  
value, so you can fail fast on the action before you attempt to hit  
the db.

Sorry bout that.

Dan

---

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 1:15am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/7 "2006-02-24T01:15:35Z")

</div>

On 2/23/06, Paul I. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Suffixing it with an exclamation mark should cause an error to be  
> raised should it fail.
> 
> Is that what you mean? Incidentally, it should be relatively trivial  
> to put together a unit test for this, probably a good way to go –  
> verify assumptions on how ActiveRecord deals with this stuff.
> 
> Regards,  
> Paul

Thanks Paul, but I’m still having problems.

My controller’s update method does not call save.

It is calling @record.update\_attributes(params[:record]).

If I try to add an ! on the end I get a syntax error.

I don’t remember replaceing save with update\_attributes, but maybe one  
of my coworkers did that. Do you mind looking at your update method  
and seeing what call it is using to update the record?

## Thanks again Greg

Greg F.  
The Norcross Group  
Forensics for the 21st Century

---

<div class="post-metadata">

**Author:** ![afg](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ecc23a/32.png) [@afg](https://www.ruby-forum.com/u/afg)\
**Post date:** [February 24, 2006, 1:21am UTC](https://www.ruby-forum.com/t/session-based-record-locking-solutions/54137/8 "2006-02-24T01:21:41Z")

</div>

I think I’m done for the night. I’ll look into this tomorrow with fresh  
eyes.

On 2/23/06, Dan S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 1. user2 saves modelA but lock version of model (0) does not match
> 
> > Regards,
> > 
> > > > handling the ActiveRecord::StaleObjectError if/when it is thrown.
> > > 
> > > a single client, but one was firefox and one was IE. I assume that  
> > > Rails mailing list  
> > > removed\_email\_address@domain.invalid  
> > > [http://lists.rubyonrails.org/mailman/listinfo/rails](http://lists.rubyonrails.org/mailman/listinfo/rails)
> 
> * * *
> 
> Rails mailing list  
> removed\_email\_address@domain.invalid  
> [http://lists.rubyonrails.org/mailman/listinfo/rails](http://lists.rubyonrails.org/mailman/listinfo/rails)

–  
Greg F.  
The Norcross Group  
Forensics for the 21st Century
