ruby 43 lines · 7 steps

Safe inventory updates in Rails

Row locks and optimistic locking keep concurrent stock changes from corrupting each other.

Explained by highlit
1class InventoryItem < ApplicationRecord
2 belongs_to :warehouse
3 
4 validates :quantity, numericality: { greater_than_or_equal_to: 0 }
5 
6 def reserve!(amount)
7 with_lock do
8 raise InsufficientStock, "only #{quantity} available" if amount > quantity
9 
10 update!(quantity: quantity - amount, reserved_at: Time.current)
11 end
12 end
13end
14 
15class InventoryItemsController < ApplicationController
16 before_action :set_item
17 
18 def update
19 @item.assign_attributes(item_params)
20 
21 if @item.save
22 redirect_to @item, notice: "Inventory updated."
23 else
24 render :edit, status: :unprocessable_entity
25 end
26 rescue ActiveRecord::StaleObjectError
27 @item.reload
28 flash.now[:alert] =
29 "This item was changed by someone else while you were editing. " \
30 "Review the latest values and try again."
31 render :edit, status: :conflict
32 end
33 
34 private
35 
36 def set_item
37 @item = InventoryItem.find(params[:id])
38 end
39 
40 def item_params
41 params.require(:inventory_item).permit(:quantity, :sku, :bin_location, :lock_version)
42 end
43end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Wrap read-then-write logic in a database lock so two requests can't act on stale quantities.
  2. 2Optimistic locking lets edits proceed unblocked but rejects saves that raced against a concurrent change.
  3. 3Turn concurrency conflicts into clear, actionable feedback instead of silent data loss.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Safe inventory updates in Rails — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code