Build on Rails

Build an inventory app on Rails

Track products, stock, and suppliers on the Rails models you already have. Avo gives your warehouse and buying team a real inventory app, with every stock change recorded, inside your own app.

250+ paying companies · 2.7M downloads of the avo gem

01

01 · the hand-built version

What building an inventory app by hand actually costs

Inventory is unforgiving. The moment a stock number is wrong, someone oversells, over-orders, or spends an afternoon reconciling. Hand-built inventory tools tend to fail in exactly those spots.

  • 01

    Stock counts drift the moment two things touch them

    Sales, returns, receipts, and transfers all move stock. Without a disciplined record of every adjustment, the on-hand number and the shelf slowly disagree, and no quick fix makes them agree again.

  • 02

    'Why is this number wrong' has no answer

    When a count looks off, you need to see who changed it, when, by how much, and why. A hand-built admin that overwrites a quantity column in place throws that history away, so every discrepancy becomes a guess.

  • 03

    Reorder lives in someone's head

    Reorder points and low-stock warnings end up in a spreadsheet or a person's memory. You find out you are out of a fast-moving SKU when a customer's order cannot ship, not before.

  • 04

    Multiple locations multiply the mess

    Stock per warehouse, transfers between them, and one honest global view is a real modeling problem. A rushed internal tool usually models a single location and breaks the day you add a second.

02

02 · the Avo version

Your models are already the hard part. Avo is the rest.

Your schema already knows the truth about stock; Avo turns it into the screens your warehouse and buying team work in. Define a resource for each model, Product, Supplier, PurchaseOrder, StockAdjustment, and because stock adjustments are their own records, the history is built into the data model instead of bolted on later.

Products and SKUs on your real schema

A Product resource gives you full CRUD over the catalog you already have, with SKU, unit price, and stock on hand as fields. Avo renders the list, filters, and forms on top. See https://docs.avohq.io/4.0/resources.html.

An audit trail, because adjustments are records

Model each stock change as a StockAdjustment with a delta, a reason, and a user, then expose it as a has_many on the product. Every count change becomes a row you can read back, so the history is never lost.

Suppliers and purchase orders, connected

belongs_to and has_many fields wire products to suppliers and receive purchase orders against them. The buying side of the app is the same associations you already modeled, made navigable.

Catch low stock before it bites

A scope for items below their reorder point and a status badge for in-stock, low, and out turn reordering into a filtered list your buyer works through, instead of a surprise at fulfillment.

The warehouse verbs, as buttons

Actions let staff receive a shipment, adjust a count, or transfer stock between locations in one click, and because each action writes an adjustment record, the audit trail keeps itself.

The right access for floor and office

Pundit-style policies let warehouse staff record counts while only buyers create purchase orders, so the app is safe to put on a tablet on the floor. See https://docs.avohq.io/4.0/authorization.html.

A Product resource with its stock history, the whole file:

class Avo::Resources::Product < Avo::BaseResource
  self.title = :name
  self.includes = [:supplier]

  def fields
    field :id, as: :id
    field :sku, as: :text, required: true
    field :name, as: :text, required: true
    field :supplier, as: :belongs_to
    field :unit_price, as: :money
    field :stock_on_hand, as: :number, sortable: true
    field :reorder_point, as: :number
    field :status, as: :badge, enum: ::Product.statuses
    field :stock_adjustments, as: :has_many
    field :purchase_orders, as: :has_many
  end
end
03

03 · the timeline

From first resource to the team running on it

Hour one

Generate resources for Product, Supplier, and StockAdjustment on the schema you already have. You are browsing the real catalog and reading a product's stock history right away.

The first afternoon

Add a low-stock scope, a status badge, and a 'Receive shipment' action that writes an adjustment. The app starts protecting the count instead of just displaying it.

Day one

Put it behind your existing auth with policies for floor staff and buyers, then ship it. The warehouse records counts and receives stock in production, on real data.

By the end of the week

The team runs stock from Avo. The reconciliation spreadsheet and the write-in-place admin retire, and every quantity change is now an auditable record in your own app.

Prefer to prompt?

Hand this to Claude Code, Cursor, or whatever agent you build with, and review what it ships like any other pull request.

Scaffold a brand-new Ruby on Rails inventory app from scratch, with Avo 4 as the management UI (https://avohq.io, docs at https://docs.avohq.io/4.0/). There is no code yet, so build the whole thing.

1. Generate the application with rails new using current Rails defaults. Set up sign-in with Rails' built-in authentication generator (bin/rails generate authentication), then add the avo gem, bundle, and run bin/rails generate avo:install. Mount Avo at /avo and put it behind that authentication so only signed-in staff reach the admin.
2. Design the data model from first principles before writing a single migration. Reason about what running stock actually requires: the item being tracked and its identifiers, how on-hand quantity is held, who supplies it, how replenishment comes in, and how counts move over time. Decide which states belong on a column as an enum and which deserve their own table, and how these entities associate. Hold one rule no matter what shape you choose: never overwrite a quantity in place. Every change to a count is its own record carrying a signed delta, a reason, and the user behind it, so the history lives in the data rather than being erased on each edit. Write down the models and associations you settled on and why, then generate the migrations and run them.
3. For each model run bin/rails generate avo:resource and fill it in concretely: self.title for a human label, self.search so the catalog is findable, self.includes to preload the associations each screen touches. Match field types to the columns you created, text for identifiers like a SKU, money for prices, a sortable number for quantities, badge over any status enum, belongs_to and has_many for the associations, and surface the change-history records as a has_many so a quantity's past reads straight off the item. See https://docs.avohq.io/4.0/resources.html.
4. Turn the warehouse verbs into Avo Actions: receiving a shipment, correcting a count, moving stock between locations. Since the app is new, put the real work in model methods or small service objects (for example a method that applies a signed adjustment inside a transaction), and have each action call into that logic and write the change record from step 2, both sides when stock moves, so the audit trail maintains itself.
5. Add filters and a scope that surface items sitting below their reorder threshold, so whoever buys works a filtered low-stock list instead of guessing, and build a dashboard with cards for total stock value, low-stock count, and recent adjustments so the state of the warehouse reads at a glance (https://docs.avohq.io/4.0/dashboards.html).
6. Authorization with Pundit, matching the roles this app needs: floor staff record counts while only buyers raise replenishment (https://docs.avohq.io/4.0/authorization.html).
7. Seed realistic sample data in db/seeds.rb, products across several suppliers with varied stock levels, a couple already below reorder point, and a spread of past adjustments, so every list, filter, and dashboard card has something to show on first boot.
8. Boot the app, sign in, open /avo, receive a shipment against a product, and confirm its stock history shows the new adjustment with the delta, the reason, and who made it.

04 · start today

Stand up an inventory app this week

Avo is per app with unlimited users, so the whole team works from it without the bill scaling with headcount. When you hit an edge Avo doesn't cover, you drop to plain Rails instead of filing a feature request.

More things teams run from their Rails app

Frequently asked questions

Can I build an inventory management system with Ruby on Rails?
Yes. Products, stock levels, suppliers, and purchase orders map directly onto Active Record models and associations. The hard part is the operational discipline: recording every adjustment, flagging low stock, and controlling who can change counts. Avo gives you that admin layer on top of your models so you focus on the inventory rules.
What is the fastest way to build an inventory app in Rails?
Model your products, suppliers, and stock adjustments, then let Avo resources render the screens. You skip building the catalog list, the forms, and the filters by hand, and stock history comes for free because adjustments are their own records. A working inventory app on real data is realistic on the first day.
Does Avo work with my existing Rails models?
Yes. Avo builds its screens from the schema you already migrated: point it at Product, Supplier, and StockAdjustment and the associations between them arrive as linked panels and lookups. Nothing about your inventory data moves or changes shape; the admin is a layer over it.
How do I keep an audit trail of stock changes?
Model each change as a StockAdjustment record with a delta, a reason, and the user who made it, rather than overwriting a quantity column. Expose it as a has_many on the product and every count change becomes a readable row. Wiring stock actions to write these records means the audit trail maintains itself.
Can I track stock across multiple locations?
Yes. Because it is your Rails schema, you can model stock per location and transfers between them however your operation actually works. Avo renders those models as screens and filters, and a transfer action can move stock while writing an adjustment on both sides, so the global view stays correct.
Can I set reorder points and low-stock alerts?
Yes. Store a reorder point on each product and add a scope that lists everything below it, so your buyer works a filtered low-stock list instead of guessing. A status badge for in-stock, low, and out makes the state obvious at a glance on the resource Index view.