If you will allow me my 2cents 
Record locking is one of the ‘not invented here’ features of most RDBMS’s and hence Rails 
We added an abstract class which all models inherits from (instead of ActiveRecord::Base) and implemented a few “core” methods on this class (and made sure all migrations of new models contains a ‘locked_by int’ field)
def can_edit?(usr)
has usr permissions (with CanCan or else how)
end
def locked?(user_id)
exec “update #{table_name} set locked_by=#{user_id} where id=#{id} and locked_by=0”
end
which allowed us to do this (in the controllers)
def edit
…
if can_edit?(current_user) && locked?(current_user)
# render like any other day
else
# inject a flash with the error (either no edit permissions or not locked by current_user)
end
end
def update
…
params[:what_ever][:locked_by]=0
if resource.update_attributes(params[:what_ever])
..
end
Currently, we are looking into the “collateral damage” (users starting to editing a record and then leaving for coffee, having a stroke or just plain drifts about in there, like it was Google search - leaving a bunch of locked records in their wake) - but hey, any solution is the offspring to a new challenge, right 
Originally we tried with optimistic locking and we did not like it at all - too many users saving data on top of each other - but then again that may just have been us implementing it the wrong way 
Like I said - just my 2cents - and probably not what you wanted <:)
cheers
Walther
ps. the above code is part pseudo-code - part copy/paste - you’d get the drift if it suits you, and ironing the ‘small-print’ out would not be a big feast 
If you will allow me my 2cents 
Record locking is one of the ‘not invented here’ features of most RDBMS’s and hence Rails 
We added an abstract class which all models inherits from (instead of ActiveRecord::Base) and implemented a few “core” methods on this class (and made sure all migrations of new models contains a ‘locked_by int’ field)
def can_edit?(usr)
has usr permissions (with CanCan or else how)
end
def locked?(user_id)
exec “update #{table_name} set locked_by=#{user_id} where id=#{id} and locked_by=0”
end
which allowed us to do this (in the controllers)
def edit
…
if can_edit?(current_user) && locked?(current_user)
# render like any other day
else
# inject a flash with the error (either no edit permissions or not locked by current_user)
end
end
def update
…
params[:what_ever][:locked_by]=0
if resource.update_attributes(params[:what_ever])
..
end
Currently, we are looking into the “collateral damage” (users starting to editing a record and then leaving for coffee, having a stroke or just plain drifts about in there, like it was Google search - leaving a bunch of locked records in their wake) - but hey, any solution is the offspring to a new challenge, right 
What you’ve implemented is pessimistic locking, which is completely different and comes with its own set of tradeoffs. If you expect conflicts to be rare, you should use optimistic locking (you’re ‘optimistic’ the lock isn’t needed). If you expect them to be common, you need to lock more actively.
Originally we tried with optimistic locking and we did not like it at all - too many users saving data on top of each other - but then again that may just have been us implementing it the wrong way 
This is exactly what optimistic locking is meant to prevent, users can’t save data over the top of each other if you’re using optimistic locking correctly.
Yes, to be clear I’m only talking about optimistic locking here.