All Projects → peek-travel → ecto_diff

peek-travel / ecto_diff

Licence: MIT License
Generates a data structure describing the difference between two ecto structs

Programming Languages

elixir
2628 projects
shell
77523 projects

Labels

Projects that are alternatives of or similar to ecto diff

Ex audit
Ecto auditing library that transparently tracks changes and can revert them.
Stars: ✭ 214 (+872.73%)
Mutual labels:  diff, ecto
Aehnlich
Show/Merge differences in directories and their content (text files) in Light/Dark designs
Stars: ✭ 73 (+231.82%)
Mutual labels:  diff
TyStrings
strings file tool for iOS / macOS developers
Stars: ✭ 15 (-31.82%)
Mutual labels:  diff
comeonin ecto password
Ecto type for saving encrypted passwords using Comeonin
Stars: ✭ 34 (+54.55%)
Mutual labels:  ecto
diff-check
Incremental code analysis tools based on checkstyle, pmd and jacoco
Stars: ✭ 48 (+118.18%)
Mutual labels:  diff
magit-diff-flycheck
Flycheck for Magit diff buffers!
Stars: ✭ 24 (+9.09%)
Mutual labels:  diff
robotframework-difflibrary
Robot Framework keyword library that will provide Diff capabilities
Stars: ✭ 23 (+4.55%)
Mutual labels:  diff
ecto generator
Generate Ecto schemas from existing database in Phoenix - Elixir
Stars: ✭ 20 (-9.09%)
Mutual labels:  ecto
wenaox
🐬 A light weight and good performance micro channel small program state management library
Stars: ✭ 33 (+50%)
Mutual labels:  diff
gitree
Print a directory tree that shows Git status and ignores files dictated by .gitignore.
Stars: ✭ 32 (+45.45%)
Mutual labels:  diff
tainted
Tool to determine which Go packages need to be rebuilt in a monorepo
Stars: ✭ 53 (+140.91%)
Mutual labels:  diff
vcdiff
Heavily optimized .NET Core vcdiff library
Stars: ✭ 16 (-27.27%)
Mutual labels:  diff
Differ
Swift library to generate differences and patches between collections.
Stars: ✭ 612 (+2681.82%)
Mutual labels:  diff
winmerge2011
Fork of WinMerge which has a different set of features
Stars: ✭ 36 (+63.64%)
Mutual labels:  diff
array-diff-multidimensional
Compare the difference between two multidimensional arrays in PHP
Stars: ✭ 60 (+172.73%)
Mutual labels:  diff
npmfs
javascript package inspector
Stars: ✭ 90 (+309.09%)
Mutual labels:  diff
HandySub
Download Subtitle from Subscene and other sources
Stars: ✭ 42 (+90.91%)
Mutual labels:  diff
tmux-eaw-fix
tmux 2.6 以降において East Asian Ambiguous Character を全角文字の幅で表示する
Stars: ✭ 16 (-27.27%)
Mutual labels:  diff
flop
Filtering, ordering and pagination for Ecto
Stars: ✭ 56 (+154.55%)
Mutual labels:  ecto
tailor
Infrastructure as Code for OpenShift
Stars: ✭ 12 (-45.45%)
Mutual labels:  diff

EctoDiff

CI Status codecov SourceLevel Hex.pm Version License Dependabot Status

Generates a data structure that describes the differences between two ecto structs. The primary use-case is to track what changed after calling Repo.insert or Repo.update, especially in conjunction with complex or deeply nested cast_assoc associations.

Installation

The package can be installed by adding ecto_diff to your list of dependencies in mix.exs:

def deps do
  [
    {:ecto_diff, "~> 0.2.2"}
  ]
end

Basic Usage

To demonstrate the basic use-case for EctoDiff, let's look at a simple example. Assume you have two related ecto schemas like the following Pet with many Skills. Importantly, we've chosen to cast_assoc the skills in the pet's changeset function, and we've opted to use on_replace: :delete on the has_many skills association.

EctoDiff structs implement the Access behaviour for working with deeply-nested data.

defmodule Pet do
  use Ecto.Schema
  import Ecto.Changeset

  schema("pets") do
    field :name, :string
    field :type, :string, default: "Cat"

    has_many :skills, Skill, on_replace: :delete
  end

  def new(params), do: changeset(%__MODULE__{}, params)
  def update(struct, params), do: changeset(struct, params)

  defp changeset(struct, params) do
    struct
    |> cast(params, [:name, :type])
    |> cast_assoc(:skills)
  end
end

defmodule Skill do
  use Ecto.Schema
  import Ecto.Changeset

  schema("skills") do
    field :name, :string
    field :level, :integer, default: 1

    belongs_to :pet, Pet
  end

  def changeset(struct, params), do: cast(struct, params, [:name, :level])
end

Now let's insert a pet into the database with three initial skills, defaulting to level: 1.

{:ok, initial_pet} =
  %{name: "Spot", skills: [%{name: "Eating"}, %{name: "Sleeping"}, %{name: "Scratching"}]}
  |> Pet.new()
  |> Repo.insert()

Later, we've decided to update this pet's name and it's skills. In this case, we're leaving "eating" alone (no changes), we're increasing "sleeping" to level: 2, we're implicitly deleting "scratching" by not including it in the list (taking advantage of on_replace: :delete), and we're adding a new skill "meowing".

[eating_id, sleeping_id, scratching_id] = Enum.map(initial_pet.skills, & &1.id)

{:ok, updated_pet} =
  initial_pet
  |> Pet.update(%{name: "Spots", skills: [%{id: eating_id}, %{id: sleeping_id, level: 2}, %{name: "Meowing"}]})
  |> Repo.update()

Now we can use EctoDiff to generate a data structure that describes all changes that occurred, making it easy to walk over all changes and act on them if desired.

iex> EctoDiff.diff(initial_pet, updated_pet)

{:ok,
 #EctoDiff<
   struct: Pet,
   primary_key: %{id: 2},
   effect: :changed,
   previous: #Pet<>,
   current: #Pet<>,
   changes: %{
     name: {"Spot", "Spots"},
     skills: [
       #EctoDiff<
         struct: Skill,
         primary_key: %{id: 5},
         effect: :changed,
         previous: #Skill<>,
         current: #Skill<>,
         changes: %{level: {1, 2}}
       >,
       #EctoDiff<
         struct: Skill,
         primary_key: %{id: 6},
         effect: :deleted,
         previous: #Skill<>,
         current: nil,
         changes: %{}
       >,
       #EctoDiff<
         struct: Skill,
         primary_key: %{id: 7},
         effect: :added,
         previous: #Skill<>,
         current: #Skill<>,
         changes: %{id: {nil, 7}, name: {nil, "Meowing"}, pet_id: {nil, 2}}
       >
     ]
   }
 >}

Detailed documentation can be found at https://hexdocs.pm/ecto_diff.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].