This guide will walk you through setting up Sow in your Elixir application and creating your first fixture.
Installation
Add sow to your dependencies in mix.exs:
def deps do
[{:sow, "~> 0.1.0"}]
endRun mix deps.get to fetch the dependency.
Configuration
Optionally configure a default repo to avoid passing it to every sync/2 call:
# config/config.exs
config :sow, repo: MyApp.RepoYour First Fixture
A fixture is a module that defines records to be synced to the database. Let's create a simple countries fixture.
1. Define the Schema
First, ensure you have an Ecto schema:
defmodule MyApp.Country do
use Ecto.Schema
schema "countries" do
field :code, :string
field :name, :string
timestamps()
end
def changeset(country, attrs) do
country
|> Ecto.Changeset.cast(attrs, [:code, :name])
|> Ecto.Changeset.validate_required([:code, :name])
end
end2. Create the Fixture Module
defmodule MyApp.Seeds.Countries do
use Sow,
schema: MyApp.Country,
keys: [:code]
def records do
[
%{code: "NO", name: "Norway"},
%{code: "SE", name: "Sweden"},
%{code: "DK", name: "Denmark"},
%{code: "FI", name: "Finland"}
]
end
end3. Sync to Database
# In your seeds.exs or any script
{:ok, countries} = MyApp.Seeds.Countries.sync(MyApp.Repo)
# Or if you configured a default repo
{:ok, countries} = MyApp.Seeds.Countries.sync()Understanding Keys
The keys option tells Sow how to identify records for upsert:
use Sow, schema: MyApp.Country, keys: [:code]When syncing:
- Sow looks for existing records where
codematches - If found: updates the record
- If not found: inserts a new record
Composite Keys
Use multiple keys for composite uniqueness:
use Sow, schema: MyApp.ProductVariant, keys: [:product_id, :sku]Default Keys
If you omit keys, Sow uses the schema's primary key:
# Uses [:id] as keys
use Sow, schema: MyApp.CountryOrganizing Fixtures
A common pattern is to organize fixtures in a Seeds namespace:
lib/my_app/seeds/
├── countries.ex
├── organizations.ex
├── products.ex
└── tags.exRunning Seeds
Development Seeds
Create a priv/repo/seeds.exs file:
alias MyApp.Seeds.{Countries, Organizations, Products}
# Sync all fixtures in dependency order
{:ok, _} = Sow.sync_all([
Countries,
Organizations,
Products
], MyApp.Repo)
IO.puts("Seeds planted successfully!")Run with:
mix run priv/repo/seeds.exs
In Migrations
You can also sync fixtures in migrations for required data:
defmodule MyApp.Repo.Migrations.SeedCountries do
use Ecto.Migration
def up do
{:ok, _} = MyApp.Seeds.Countries.sync(MyApp.Repo)
end
def down do
# Optional: remove seeded data
end
endWhat's Next?
- Learn about Associations for handling relationships
- Explore Runtime Lookups for querying existing data
- Create Wrapper Modules to share helpers