Skip to content

Instantly share code, notes, and snippets.

@abarrak
Last active August 17, 2016 20:39
Show Gist options
  • Select an option

  • Save abarrak/c3d2bd0e4a697b05bb14940a4501013e to your computer and use it in GitHub Desktop.

Select an option

Save abarrak/c3d2bd0e4a697b05bb14940a4501013e to your computer and use it in GitHub Desktop.
DB Locking in Rails

Two approaches for database locking supported natively in Rails

[1] Optimistic Locking.

Deals with conflicts when they occur by implementing a locking table attribute. It happens in application logic and does not involve database specific mechanism.

Add locking cloumn.

Class AddLockVersionToTimesheets < ActiveRecord::Migration
  def change
    add column :timesheets, :lock_version, :integer, default: 0
  end
end

Rspec.

describe Timesheet do
  it "locks optimistically" do
    t1 = Timesheet.create
    t2 = Timesheet.find t1.id
    
    t1.rate = 250
    t2.rate = 200
    
    expect(t1.save).to be_true
    expect(t2.save).to raise_error(ActiveRecord::StaleObjectError)
  end
end

Graceful handling in controller action.

  def update
    timesheet = Timesheet.find params[:id]
    timesheet.update params[:timesheet]
    redirect_to timesheets_url, notice: "successful update"
    
    rescue ActiveRecord::StaleObjectError
      flash[:alert] = "Timesheet was modified while we were editing it .."
      redirect_to [:edit, timesheet]
    end
  end

[2] Pessimistic Locking.

Assumes the worst in the beginning. Locks at the database level by means of transactions.

Timesheet.transaction do
  t = Timesheet.lock.first
  t.approved.toggle
  t.save!
end

Source: (The Rails 4 Way).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment