Last active
August 13, 2018 16:47
-
-
Save tmattio/4a9ce29b208c5c35f0b48179de3db681 to your computer and use it in GitHub Desktop.
An implementation of has_many polymorphic association with Ecto
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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