Rails seed data

Rails + PostgreSQL test data without maintaining db/seeds.rb — schema-driven generation that never drifts.

Rails projects seed through db/seeds.rb, run by rails db:seed — a script that usually grows a list of Model.create! calls or a FactoryBot loop. It works until the schema moves and the seed does not. This guide shows the Rails-native seeding workflow, where it breaks, and the schema-driven alternative.

How Rails seeding normally works

Rails owns the schema through migrations (rails db:migrate). Seeding is db/seeds.rb, run with rails db:seed (and automatically by rails db:setup / db:reset):

# db/seeds.rb
require "faker"
 
50.times do
  User.create!(
    email: Faker::Internet.email,
    name: Faker::Name.name
  )
end

Works for a standalone model. The moment Order has a belongs_to :user, the seed has to create the user first and attach it — dependency order becomes something the script encodes by hand.

Where Rails seed scripts break

  1. Foreign keys. Order.create!(user: user) needs a persisted parent. The seed grows ordering logic, and every added association is another line of bookkeeping. Skip it and you get a foreign-key violation — or a validation failure that is harder to trace.
  2. Schema drift. A new non-null column, an enum, a validates rule — each one is a seed change. db/seeds.rb is not checked against the schema, so it silently rots until a migration surfaces the gap.
  3. Uniform randomness. Faker produces plausible values, not production distributions. If your real status column is 70% active, a flat loop gives you roughly a third of each — and query plans in tests stop matching production.

Schema-driven seeding with Weavori

Weavori reads the database schema — the one Rails migrated — and generates rows from it. The Rails-specific workflow:

1. Migrate as usual
$ rails db:migrate
2. Seed from the schema
$ npx --yes @weavori/cli generate postgres://localhost:5432/mydb --rows 1000

Weavori introspects tables, foreign keys, types, and constraints, resolves dependency order (parents before children), and writes via COPY. Every generated order.user_id references a real generated user — by construction, not by association ordering.

The schema is the seed

When a Rails migration changes the schema, the generated data changes with it. There is no db/seeds.rb to update because nothing in it duplicated the schema.

Rails + Weavori in CI

The loop that keeps test databases honest:

$ rails db:migrate
$ npx --yes @weavori/cli generate $TEST_DATABASE_URL --rows 1000 --output plain

Weavori supports API keys for headless auth, standardized exit codes, and offline license validation — CI runners on restricted networks don't phone home. Full GitHub Actions / GitLab / CircleCI / Jenkins examples in the CI/CD guide.

Which Rails seed command do you need?

GoalCommand
Run db/seeds.rb against an existing databaserails db:seed
Create the database, load the schema, then seedrails db:setup
Drop, recreate, load the schema, then seedrails db:reset
Truncate every table, then seedrails db:seed:replant
Generate a production-shaped dataset with no seeds filenpx --yes @weavori/cli generate postgres://localhost:5432/mydb

rails db:seed

rails db:seed runs db/seeds.rb. Rails supplies the runner and the ActiveRecord models; the rows come from that file, so it is the file that grows ordering logic as associations appear — and the file nobody updates after a migration.

rails db:setup

db:setup creates the database, loads the schema from db/schema.rb, and runs the seed in one pass. It is the command behind a fresh clone — which is precisely why a seed that assumes existing rows works for you and fails for the next developer who joins.

rails db:reset

db:reset drops the database, recreates it from db/schema.rb, and seeds. Running it is the honest test of whether db/seeds.rb is genuinely re-runnable from an empty schema or only works against a database somebody has already populated by hand.

rails db:seed:replant

db:seed:replant truncates every table and then runs the seed — the fastest way to reseed without dropping the schema. On Rails 4 and earlier the task is rake db:seed; Rails 5 introduced the rails prefix and kept rake as an alias.

When to keep your Rails seed

Honesty about boundaries: keep db/seeds.rb for deterministic unit-test fixtures — a known user the test asserts against. Keep Faker for single values inside tests. Weavori replaces the dataset problem: filling dev, staging, and CI databases with production-shaped, FK-intact rows.

Ready to generate your first dataset?

Install Weavori in one command and connect to any PostgreSQL database.

$npm install -g @weavori/cli
macOS · Linux · Windows/No dependencies required

No credit card required. Start with a 14-day free trial of Pro, then free tier or subscribe.