Coming from Django how do you implement an abstract model in Ecto

class Lockable(models.Model):
    locked_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
    )

    class Meta:
        abstract = True

    def is_locked_by(self, locked_by):
        return self.locked_by == locked_by

    def lock(self, locked_by):
        self.locked_by = locked_by
        self.save()

    def unlock(self):
        self.locked_by = None
        self.save()


class Document(Lockable, models.Model):
    title = models.CharField(max_length=256)
    body = models.TextField()

This is the start of the Ecto schema:

defmodule FooWeb.Artifacts.Document do
  use Ecto.Schema
  import Ecto.Changeset

  schema "documents" do
    field :body, :string
    field :title, :string

    timestamps()
  end

  @doc false
  def changeset(document, attrs) do
    document
    |> cast(attrs, [:title, :body])
    |> validate_required([:title, :body])
  end
end

How to implement the Lockable code?

1 Like

Hello and welcome,

I would say You don’t… because class and inheritance are typical for OOP.

In Fp You have structures, and functions.

That said, it’s easy to translate.

def is_locked_by(struct, locked_by) do
  struct.locked_by == locked_by
end

# or more Elixir style

def is_locked_by %{locked_by: lb}, locked_by, do: lb == locked_by

You just replace self by a struct, add some do end, remove return… this function applies to any struct with locked_by.

But do not try to apply OOP concept to FP language, those are different paradigm :slight_smile:

If You want some polymorphism, check Elixir Protocols

3 Likes