Forum: Ruby on Rails When to use optimistic locking?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
0430e2423183415d7688898faddb470f?d=identicon&s=25 Jason Tuttle (Guest)
on 2006-05-09 18:26
(Received via mailing list)
Hi All,

I'm having some trouble deciding when and how to implement optimistic
locking.

Let's say I have a multiuser Rails app, and let's say it stores,
among other things "vital" customer information.

The standard methods created by the Rails generate scaffold script
look like this:

   def edit
     @customer = Customer.find(params[:id])
   end

   def update
     @customer = Customer.find(params[:id])
     if @customer.update_attributes(params[:customer])
       flash[:notice] = 'Customer was successfully updated.'
       redirect_to :action => 'show', :id => @customer
     else
       render :action => 'edit'
     end
   end

What if I want to guard against 2 people simultaneously updating the
same customer record? How would I go about doing this? I can't find
any examples online, and I'm a bit lost.

Thanks,

: )

Jason
00973881979aa0a660ffbbb2f7a907fb?d=identicon&s=25 Peter De Berdt (Guest)
on 2006-05-09 18:45
(Received via mailing list)
> What if I want to guard against 2 people simultaneously updating
> the same customer record? How would I go about doing this? I can't
> find any examples online, and I'm a bit lost.

Well, first of all, you need a lock_version column in your model
(table) (or override it with the "set_locking_column" method). If a
record has been changed by someone else, Rails will throw a
StaleObjectError, you need to trap this error and handle it
appropriately (present the user with a dialog confirming to update
the record anyway or cancel it). It's up to you to find a way to
handle the error.

Best regards

Peter De Berdt
0430e2423183415d7688898faddb470f?d=identicon&s=25 Jason Tuttle (Guest)
on 2006-05-09 20:02
Peter De Berdt wrote:
>> What if I want to guard against 2 people simultaneously updating
>> the same customer record? How would I go about doing this? I can't
>> find any examples online, and I'm a bit lost.
>
> Well, first of all, you need a lock_version column in your model
> (table) (or override it with the "set_locking_column" method). If a
> record has been changed by someone else, Rails will throw a
> StaleObjectError, you need to trap this error and handle it
> appropriately (present the user with a dialog confirming to update
> the record anyway or cancel it). It's up to you to find a way to
> handle the error.
>
> Best regards
>
> Peter De Berdt

Thanks Peter, but in the scaffold generated CRUD code, the model state
is lost between the "edit" and "update" calls. -- the StaleObjectError
will never be thrown.

: )

Jason
0430e2423183415d7688898faddb470f?d=identicon&s=25 Jason Tuttle (Guest)
on 2006-05-09 20:18
Jason Tuttle wrote:
> Hi All,
>
> I'm having some trouble deciding when and how to implement optimistic
> locking.
>
> Let's say I have a multiuser Rails app, and let's say it stores,
> among other things "vital" customer information.
>
> The standard methods created by the Rails generate scaffold script
> look like this:
>
>    def edit
>      @customer = Customer.find(params[:id])
>    end
>
>    def update
>      @customer = Customer.find(params[:id])
>      if @customer.update_attributes(params[:customer])
>        flash[:notice] = 'Customer was successfully updated.'
>        redirect_to :action => 'show', :id => @customer
>      else
>        render :action => 'edit'
>      end
>    end
>
> What if I want to guard against 2 people simultaneously updating the
> same customer record? How would I go about doing this? I can't find
> any examples online, and I'm a bit lost.
>
> Thanks,
>
> : )
>
> Jason

The more I think about it, there doesn't seem to be a way to take
advantage of Active Record's  optimistic locking when using the standard
scaffold generated CRUD approach because the model state is lost between
the call to "edit" and the subsequent call to "update". -- The
ActiveRecord::StaleObjectError will never be thrown.

Do you have to manually track the value of the lock_version column?

There must be a more elegant solution.

I must be missing something. I just can't figure out what.

- Jason
5d15c6821f3c3054c04b85471824ba7c?d=identicon&s=25 Kevin Olbrich (Guest)
on 2006-05-09 20:34
(Received via mailing list)
On Tuesday, May 09, 2006, at 8:18 PM, Jason Tuttle wrote:
>> look like this:
>>      else
>> : )
>
>Rails@lists.rubyonrails.org
>http://lists.rubyonrails.org/mailman/listinfo/rails

It works.  I think it puts a hidden text field with the value of the
lock_version in the form.  When you go to save it, it compares the value
to the one in the database.  If the one in the database is different,
then someone has modified the record.  Once saved, the value is
incremented.

So the state of the record is retained.  I think AR is smart enough to
know what to do with this without adding additional code, which is why
they call it a 'magic' column.

_Kevin
24d2f8804e6bb4b7ea6bd11e0a586470?d=identicon&s=25 Jeremy Kemper (Guest)
on 2006-05-09 20:43
(Received via mailing list)
On May 9, 2006, at 11:18 AM, Jason Tuttle wrote:
> The more I think about it, there doesn't seem to be a way to take
> advantage of Active Record's  optimistic locking when using the
> standard
> scaffold generated CRUD approach because the model state is lost
> between
> the call to "edit" and the subsequent call to "update". -- The
> ActiveRecord::StaleObjectError will never be thrown.
>
> Do you have to manually track the value of the lock_version column?

Yes.

> There must be a more elegant solution.

Wrap up the lock_version handling by passing it in session, crypted
form param, or similar.

> I must be missing something. I just can't figure out what.

A well-tested patch?  :)

Michael Schuerig did quite a bit of work on an alternate scaffolding
toolset that includes conflict resolution.  See his Boilerplate lib:
   http://www.schuerig.de/michael/boilerplate/

Best,
jeremy
0430e2423183415d7688898faddb470f?d=identicon&s=25 Jason Tuttle (Guest)
on 2006-05-09 20:56
Kevin Olbrich wrote:
> On Tuesday, May 09, 2006, at 8:18 PM, Jason Tuttle wrote:
>>> look like this:
>>>      else
>>> : )
>>
>>Rails@lists.rubyonrails.org
>>http://lists.rubyonrails.org/mailman/listinfo/rails
>
> It works.  I think it puts a hidden text field with the value of the
> lock_version in the form.  When you go to save it, it compares the value
> to the one in the database.  If the one in the database is different,
> then someone has modified the record.  Once saved, the value is
> incremented.
>
> So the state of the record is retained.  I think AR is smart enough to
> know what to do with this without adding additional code, which is why
> they call it a 'magic' column.
>
> _Kevin

Hi Kevin,

I just double checked. -- There doesn't seem to bee any hidden field.

- Jason
0430e2423183415d7688898faddb470f?d=identicon&s=25 Jason Tuttle (Guest)
on 2006-05-09 21:22
Jeremy Kemper wrote:
> On May 9, 2006, at 11:18 AM, Jason Tuttle wrote:
>> The more I think about it, there doesn't seem to be a way to take
>> advantage of Active Record's  optimistic locking when using the
>> standard
>> scaffold generated CRUD approach because the model state is lost
>> between
>> the call to "edit" and the subsequent call to "update". -- The
>> ActiveRecord::StaleObjectError will never be thrown.
>>
>> Do you have to manually track the value of the lock_version column?
>
> Yes.
>
>> There must be a more elegant solution.
>
> Wrap up the lock_version handling by passing it in session, crypted
> form param, or similar.
>
>> I must be missing something. I just can't figure out what.
>
> A well-tested patch?  :)
>
> Michael Schuerig did quite a bit of work on an alternate scaffolding
> toolset that includes conflict resolution.  See his Boilerplate lib:
>    http://www.schuerig.de/michael/boilerplate/
>
> Best,
> jeremy

Thanks Jeremy. -- I'm off to check out Boilerplate lib right now.

- Jason
This topic is locked and can not be replied to.