View Source EctoDiscriminator.Schema (ecto_discriminator v0.4.4)

Wrapper around Ecto.Schema that enables inheritance of schema fields.

It has been built to mimic Ecto.Schema as much as possible.

base-schema

Base schema

To make a base schema you have to do two things:

  1. Change use Ecto.Schema to use EctoDiscriminator.Schema:

     defmodule SomeTable do
       use EctoDiscriminator.Schema
  2. Add EctoDiscriminator.DiscriminatorType field to schema (check module documentation for more examples):

     schema "some_table" do
       field :type, EctoDiscriminator.DiscriminatorType
       ...
     end

Base schemas should ideally contain only fields that are common across all diverged schemas (like timestamps). There is no problem with having other fields defined if someone needs it for some functionality though. Any field can be overriden by diverged schema.

Diverged changeset

Base schemas have predefined function, based on DiscriminatorChangeset.diverged_changeset/2, that allows creating changesets for diverged schemas directly from base (check here for more).

diverged-schema

Diverged schema

To make a diverged schema you have to do two things:

  1. Change use Ecto.Schema to use EctoDiscriminator.Schema:

     defmodule SomeTable.Foo do
       use EctoDiscriminator.Schema
  2. Define schema with name of base schema as a source:

     schema SomeTable do
       field ...
       ...
     end

Diverged schemas can contain any field supported by Ecto.Schema.

Inheriting struct-related stuff

@derive

Any @derive declarations put in base schema will be applied to the diverged schema. You can still overwrite those for particular schema if needed.

Going back to base struct

Base struct

Diverged schemas have predefined function to_base/1 that applies simple modifications in order to get base struct from diverged.

Base changeset

Diverged schemas have predefined function, based on DiscriminatorChangeset.base_changeset/2, that allows creating changesets for base schemas directly from diverged (check here for more).

Casting base fields

Diverged schemas have predefined function, based on DiscriminatorChangeset.cast_base/2, that allows running base changesets inside changeset of diverged schema (check here for more).

querying

Querying

Diverged schemas have some logic injected that allows very simple querying:

MyApp.Repo.all(SomeTable.Foo)

This will generate SQL similar to this:

SELECT ... FROM some_table WHERE discriminator = "Elixir.SomeTable.Foo"

This functionality should be enough in most cases, however if the injected where condition causes some issues (eg. in some advanced SQL) you can exclude it on the beginning:

SomeTable.Foo
|> exclude(:where)
|> MyApp.Repo.all()
#=> SELECT ... FROM some_table

Link to this section Summary

Functions

Main building block for inheritance logic.

Link to this section Functions

Link to this macro

schema(source, list)

View Source (macro)

Main building block for inheritance logic.

schema/2 wraps Ecto.Schema.schema/2, adding some features required to support idea of this library.

For base schema, source should be the name of a DB table:

schema "some_table" do

For diverged schema, source must be the name of a base module:

schema SomeTable do

Additionally, inside schema/2 of the base schema you have to add field which will be acting as a discriminator:

field :type, EctoDiscriminator.DiscriminatorType
Link to this function

to_base(struct, destination)

View Source