Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ Supported formats:
* [DBML](https://www.dbml.org/)
* [QuickDBD](https://www.quickdatabasediagrams.com)
* [Mermaid](https://mermaid-js.github.io/mermaid/#/entityRelationshipDiagram)
* [D2](https://d2lang.com)

![Simple blog demo](assets/simple_blog_dot_demo.png)

The **D2** format renders the rich tier — clusters, `Ecto.Enum` values, embedded schemas, and primary/foreign keys:

![Simple blog demo (D2)](assets/simple_blog_d2_demo.svg)

<details>
<summary>Definition of schemas</summary>

Expand Down
95 changes: 95 additions & 0 deletions assets/simple_blog_d2_demo.svg

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please remove this demo file? I understand the point, and nothing is wrong with the image. DOT is the de facto default here and the README carries a single demo. How to present several formats is a separate question I want to think through on its own rather than settle in this PR.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 20 additions & 14 deletions examples_generator.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ defmodule Ecto.ERD.ExamplesGenerator do
require Logger

@shared_examples [
[name: "Default", formats: [:dbml, :dot, :qdbd, :puml, :mmd]],
[name: "Default", formats: [:dbml, :dot, :qdbd, :puml, :mmd, :d2]],
[
name: "No fields",
formats: [:dot, :mmd],
formats: [:dot, :mmd, :d2],
config: """
[
columns: []
Expand All @@ -14,7 +14,7 @@ defmodule Ecto.ERD.ExamplesGenerator do
],
[
name: "Contexts as clusters",
formats: [:dbml, :dot, :puml],
formats: [:dbml, :dot, :puml, :d2],
config: """
alias Ecto.ERD.Node

Expand All @@ -32,7 +32,7 @@ defmodule Ecto.ERD.ExamplesGenerator do
],
[
name: "Contexts as clusters (no fields)",
formats: [:dot, :puml],
formats: [:dot, :puml, :d2],
config: """
alias Ecto.ERD.Node

Expand Down Expand Up @@ -150,7 +150,7 @@ defmodule Ecto.ERD.ExamplesGenerator do
],
[
name: "Only embedded schemas",
formats: [:dot, :puml],
formats: [:dot, :puml, :d2],
config: """
alias Ecto.ERD.Node

Expand All @@ -167,11 +167,12 @@ defmodule Ecto.ERD.ExamplesGenerator do
}

@formats %{
dot: %{examples_dir: "examples/dot", name: "DOT", image?: true},
dbml: %{examples_dir: "examples/dbml", name: "DBML", image?: false},
qdbd: %{examples_dir: "examples/quick_dbd", name: "QuickDBD", image?: false},
puml: %{examples_dir: "examples/plantuml", name: "PlantUML", image?: true},
mmd: %{examples_dir: "examples/mermaid", name: "Mermaid", image?: false}
dot: %{examples_dir: "examples/dot", name: "DOT", image_ext: "png"},
dbml: %{examples_dir: "examples/dbml", name: "DBML"},
qdbd: %{examples_dir: "examples/quick_dbd", name: "QuickDBD"},
puml: %{examples_dir: "examples/plantuml", name: "PlantUML", image_ext: "png"},
mmd: %{examples_dir: "examples/mermaid", name: "Mermaid"},
d2: %{examples_dir: "examples/d2", name: "D2", image_ext: "svg"}
}

def run(source_url_root) do
Expand Down Expand Up @@ -235,8 +236,8 @@ defmodule Ecto.ERD.ExamplesGenerator do
])

image_url =
if @formats[format].image? do
Path.rootname(document_url) <> ".png"
if image_ext = @formats[format][:image_ext] do
Path.rootname(document_url) <> "." <> image_ext
end

[
Expand Down Expand Up @@ -313,10 +314,11 @@ defmodule Ecto.ERD.ExamplesGenerator do
end

{:ok, new_output_content} = File.read(output_path)
image_ext = @formats[format][:image_ext]

if @formats[format].image? and
if image_ext &&
(old_output_content != new_output_content or
not File.exists?(Path.rootname(output_path) <> ".png")) do
not File.exists?(Path.rootname(output_path) <> "." <> image_ext)) do
Logger.debug("Generating image from #{output_path}")
generate_image(format, output_path)
end
Expand All @@ -333,6 +335,10 @@ defmodule Ecto.ERD.ExamplesGenerator do
System.cmd("plantuml", [file], env: %{"PLANTUML_LIMIT_SIZE" => "8192"})
end

defp generate_image(:d2, file) do
System.cmd("d2", [file, Path.rootname(file) <> ".svg"])
end

defp init_project(project_name, repo, commit) do
Logger.debug("#{project_name}: clone repo")
System.cmd("git", ["clone", repo, project_name], cd: "tmp/repos")
Expand Down
1 change: 1 addition & 0 deletions lib/ecto/erd/document.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule Ecto.ERD.Document do
when is_function(map_node_callback, 1) do
document_module =
case format do
".d2" -> Ecto.ERD.Document.D2
".dbml" -> Ecto.ERD.Document.DBML
".dot" -> Ecto.ERD.Document.Dot
".mmd" -> Ecto.ERD.Document.Mermaid
Expand Down
Loading