Skip to content

Instantly share code, notes, and snippets.

@tmattio
Last active August 13, 2018 16:47
Show Gist options
  • Save tmattio/4a9ce29b208c5c35f0b48179de3db681 to your computer and use it in GitHub Desktop.
Save tmattio/4a9ce29b208c5c35f0b48179de3db681 to your computer and use it in GitHub Desktop.
An implementation of has_many polymorphic association with Ecto
defmodule CreateCat do
use Ecto.Migration
def change do
create table(:cats) do
end
end
end
defmodule CreateDog do
use Ecto.Migration
def change do
create table(:dogs) do
end
end
end
defmodule CreatePetOwner do
use Ecto.Migration
def change do
create table(:pet_owners) do
end
end
end
defmodule CreateAnimal do
use Ecto.Migration
def change do
create table(:animals) do
add(:owner_id, references(:pet_owners, on_delete: :nothing))
add(:dog_id, references(:dogs, on_delete: :nothing))
add(:cat_id, references(:cats, on_delete: :nothing))
end
create(index(:animals, [:owner_id]))
create(unique_index(:animals, [:dog_id]))
create(unique_index(:animals, [:cat_id]))
create(constraint(:animals, :has_only_one_reference, check: "(
(dog_id is not null)::integer +
(cat_id is not null)::integer
) = 1"))
end
end
defmodule Animal do
use Ecto.Schema
import Ecto.Changeset
@required_fields ~w(owner)a
@optional_fields ~w(dog_id cat_id)a
schema "animals" do
# Common fields to all animals
belongs_to(:owner, PetOwner)
# References to each concrete animal table
belongs_to(:dog, Dog)
belongs_to(:cat, Cat)
end
def changeset(animal, attrs) do
animal
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> unique_constraint(:dog_id)
|> unique_constraint(:cat_id)
|> check_constraint(:has_only_one_reference)
end
end
defmodule Dog do
use Ecto.Schema
schema "dogs" do
end
end
defmodule Cat do
use Ecto.Schema
schema "cats" do
end
end
defmodule PetOwner do
use Ecto.Schema
schema "pet_owners" do
has_many(:pet, Animal)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment