Skip to content

bruce/diffident

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Diffident

Generate structural diffs between two Elixir values.

Examples

A simple example:

left = %{name: "Alice", age: 30}
right = %{name: "Alice", age: 31, city: "NYC"}

Diffident.explain(left, right)
# Returns:
#   [
#    {:changed, [:age], 30, 31},
#    {:added, [:city], "NYC"}
#   ]

Here's one returning more complex structural changes:

left = %{
  user: [
    %{id: 1, name: "Alice"},
    %{id: 2, name: "Bob"}
  ],
  meta: {:ok, %{count: 2}}
}

right = %{
  user: [
    %{id: 1, name: "Alice"},
    %{id: 2, name: "Robert"},
    %{id: 3, name: "Carol"}
  ],
  meta: {:ok, %{count: 3}}
}

Diffident.explain(left, right)
# Returns:
#   [
#     {:changed, [:user, {Access, :at, [1]}, :name], "Bob", "Robert"},
#     {:added, [:user, {Access, :at, [2]}], %{id: 3, name: "Carol"}},
#     {:changed, [:meta, {Access, :elem, [1]}, :count], 2, 3}
#.  ]

Note that the paths returned are serializable; rather than Access function calls, MFAs are returned, but you can convert them using Diffident.to_access_compatible/1:

Diffident.to_access_compatible([:user, {Access, :at, [1]}, :name])
# Returns:
#   [:user, Access.at(1), :name]

Skip that intermediate step to use the path directly with Diffident.get_in/2:

data = %{a: [1, %{b: 2}]}
path = [:a, {Access, :at, [1]}, :b]

Diffident.get_in(data, path)
# Returns:
#   2

They work with Diffident.put_in/3, too:

data = {[%{x: 1}], 99}
path = [{Access, :elem, [0]}, {Access, :at, [0]}, :x]

updated = Diffident.put_in(data, path, 7)

Diffident.get_in(updated, path) == 7
# Returns:
#   true

updated == {[%{x: 7}], 99}
# Returns:
#   true

Installation

def deps do
  [
    {:diffident, "~> 0.1.0"}
  ]
end

License

See LICENSE.

About

Generate structural diffs between two Elixir values.

Topics

Resources

License

Stars

Watchers

Forks

Languages