Skip to content

Instantly share code, notes, and snippets.

@nurugger07
Last active January 11, 2019 16:08
Show Gist options
  • Save nurugger07/3004a6ded7cba408b848c70f790fb50a to your computer and use it in GitHub Desktop.
Save nurugger07/3004a6ded7cba408b848c70f790fb50a to your computer and use it in GitHub Desktop.

First create a function to handle the soft delete

defmodule MyApp.Repo.Migrations.SoftDeletes do
  use Ecto.Migration

  def up do
    execute """
      CREATE FUNCTION soft_delete() RETURNS TRIGGER AS $$
        DECLARE
          command text := ' SET deleted_at = current_timestamp where id = $1';
        BEGIN
          EXECUTE 'UPDATE ' || TG_TABLE_NAME || command USING OLD.id;
          RETURN OLD;
        END;
      $$ LANGUAGE plpgsql;
    """
  end

  def down do
    execute """
      DROP FUNCTION soft_delete();
    """
  end
end

Then create the migration for you table & view

defmodule MyApp.Repo.Migrations.CreateWidgets do
  use Ecto.Migration

  def up do
    create table("all_widgets") do
      add :name, :string
      add :deleted_at, :utc_datetime
      timestamps(type: :utc_datetime)
    end

    create index("all_widgets", [:deleted_at], where: "deleted_at IS NULL", name: :widgets_deleted_at_idx)

    execute """
    CREATE VIEW widgets AS
    SELECT * FROM all_widgets WHERE deleted_at IS NULL;
    """

    execute """
    CREATE TRIGGER widgets_soft_delete_tg
    INSTEAD OF DELETE ON widgets
    FOR EACH ROW EXECUTE PROCEDURE soft_delete();
    """
  end

  def down do
    execute "DROP VIEW widgets;"
    drop table("all_widgets")
  end

end

The Ecto schema doesn't change for this. You just create a schema as you would for the widgets view. Inserts, updates, and deletes all work against the view and your Elixir code is none the wiser

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment