rails-erd 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES.md +16 -0
- data/README.md +58 -26
- data/lib/rails_erd/cli.rb +10 -0
- data/lib/rails_erd/config.rb +6 -1
- data/lib/rails_erd/diagram/mermaid.rb +22 -21
- data/lib/rails_erd/diagram.rb +63 -8
- data/lib/rails_erd/version.rb +1 -1
- data/lib/rails_erd.rb +2 -0
- data/test/test_helper.rb +1 -1
- data/test/unit/config_test.rb +11 -0
- data/test/unit/diagram_test.rb +82 -0
- data/test/unit/mermaid_test.rb +18 -1
- metadata +2 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e8c66456b4d4e9279e9957ffd932fb244aa160c7f271c67cfafec1217161e232
|
|
4
|
+
data.tar.gz: 70f6317d8e825c273f70495e9eb9f41e4576dea96e4065d8627f45558b5f3cc4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d7925eb9de863885b214caf8efb6b43b935c5d34df50134d54118aa5924d927bf1cb23ac3bc22ee2f5fb75e0fd59cf63c65873178e90516bc220645c904405ab
|
|
7
|
+
data.tar.gz: 5f9a9910107772a49ead53f939f1fbf7a553df44ffbe59ffeb3796c7dea3d1f40a06cac449aa7d23d83efc26a2aa42181279014fc09d2fe2588a9ab9b82a972b
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,19 @@
|
|
|
1
|
+
Unreleased
|
|
2
|
+
----------
|
|
3
|
+
|
|
4
|
+
2.2.0
|
|
5
|
+
-----
|
|
6
|
+
|
|
7
|
+
### New Features
|
|
8
|
+
* Add `only_attributes` option to show only the listed attributes on a per-model basis, the counterpart to `exclude_attributes` (#486, #487)
|
|
9
|
+
* Add `recursive` option (default `true`); set it to `false` to omit self-referential relationships, such as a `parent_id` pointing at the entity's own table (#483, #485)
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
* Mermaid no longer draws entities that were filtered out of the diagram: an edge is only emitted when both of its entities were drawn, matching the Graphviz generator (#482, #484)
|
|
13
|
+
|
|
14
|
+
### Internal
|
|
15
|
+
* Remove unnecessary `ostruct` runtime dependency; replace stale `pry-nav` with `pry-byebug` (#481)
|
|
16
|
+
|
|
1
17
|
2.1.0
|
|
2
18
|
-----
|
|
3
19
|
|
data/README.md
CHANGED
|
@@ -145,44 +145,20 @@ mermaid_style: erdiagram
|
|
|
145
145
|
notation: simple
|
|
146
146
|
orientation: horizontal
|
|
147
147
|
polymorphism: false
|
|
148
|
+
recursive: true
|
|
148
149
|
sort: true
|
|
149
150
|
warn: true
|
|
150
151
|
title: true
|
|
151
152
|
exclude: null
|
|
152
153
|
exclude_attributes: null
|
|
153
154
|
only: null
|
|
155
|
+
only_attributes: null
|
|
154
156
|
only_recursion_depth: null
|
|
155
157
|
prepend_primary: false
|
|
156
158
|
cluster: false
|
|
157
159
|
splines: spline
|
|
158
160
|
```
|
|
159
161
|
|
|
160
|
-
### Hiding attributes for specific models
|
|
161
|
-
|
|
162
|
-
While `attributes: false` hides attributes for *every* model, `exclude_attributes`
|
|
163
|
-
lets you hide attributes for individual models without affecting the others. Map a
|
|
164
|
-
model name to `true` to hide all of its attributes, or to a list of attribute names
|
|
165
|
-
to hide only those:
|
|
166
|
-
|
|
167
|
-
```yaml
|
|
168
|
-
exclude_attributes:
|
|
169
|
-
BigTable: true # hide all attributes for BigTable
|
|
170
|
-
User: # hide only these attributes for User
|
|
171
|
-
- password_digest
|
|
172
|
-
- remember_token
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
From the command line, pass a comma separated list where each entry is either
|
|
176
|
-
`Model` (hide all of its attributes) or `Model.attribute` (hide a single one):
|
|
177
|
-
|
|
178
|
-
```bash
|
|
179
|
-
# rake task (bare key=value)
|
|
180
|
-
bundle exec rake erd exclude_attributes="BigTable,User.password_digest,User.remember_token"
|
|
181
|
-
|
|
182
|
-
# erd binary (flags require the -- prefix)
|
|
183
|
-
bundle exec erd --exclude_attributes="BigTable,User.password_digest,User.remember_token"
|
|
184
|
-
```
|
|
185
|
-
|
|
186
162
|
### Filtering models with exclude and only
|
|
187
163
|
|
|
188
164
|
Use `exclude` to hide specific models from the diagram, or `only` to show only
|
|
@@ -236,6 +212,62 @@ exclude:
|
|
|
236
212
|
- Only `i`, `m`, `x` regex flags are supported; other flags are ignored
|
|
237
213
|
- When both `exclude` and `only` are specified, `only` is applied first, then `exclude`
|
|
238
214
|
|
|
215
|
+
### Filtering attributes with exclude_attributes and only_attributes
|
|
216
|
+
|
|
217
|
+
The `attributes` option selects which *kinds* of attributes are displayed for
|
|
218
|
+
every model. `only_attributes` and `exclude_attributes` refine that per model,
|
|
219
|
+
mirroring the way `only` and `exclude` filter entities: use `only_attributes` to
|
|
220
|
+
show just a few attributes of a model, or `exclude_attributes` to hide a few.
|
|
221
|
+
Both are keyed by model name, and models that are not listed keep all of their
|
|
222
|
+
attributes.
|
|
223
|
+
|
|
224
|
+
**Showing only some attributes** — map a model name to the attributes to keep:
|
|
225
|
+
|
|
226
|
+
```yaml
|
|
227
|
+
only_attributes:
|
|
228
|
+
Book:
|
|
229
|
+
- title
|
|
230
|
+
- isbn
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Hiding some attributes** — map a model name to the attributes to hide, or to
|
|
234
|
+
`true` to hide all of them:
|
|
235
|
+
|
|
236
|
+
```yaml
|
|
237
|
+
exclude_attributes:
|
|
238
|
+
BigTable: true # hide all attributes for BigTable
|
|
239
|
+
User: # hide only these attributes for User
|
|
240
|
+
- password_digest
|
|
241
|
+
- remember_token
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
From the command line, both take a comma separated list of `Model.attribute`
|
|
245
|
+
entries. `exclude_attributes` additionally accepts a bare `Model` to hide all of
|
|
246
|
+
its attributes:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
# rake task (bare key=value)
|
|
250
|
+
bundle exec rake erd only_attributes="Book.title,Book.isbn"
|
|
251
|
+
bundle exec rake erd exclude_attributes="BigTable,User.password_digest,User.remember_token"
|
|
252
|
+
|
|
253
|
+
# erd binary (flags require the -- prefix)
|
|
254
|
+
bundle exec erd --only_attributes="Book.title,Book.isbn"
|
|
255
|
+
bundle exec erd --exclude_attributes="BigTable,User.password_digest,User.remember_token"
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Notes:**
|
|
259
|
+
|
|
260
|
+
- Unlike `only`, listing a model in `only_attributes` does not affect any other
|
|
261
|
+
model; unlisted models keep all of their attributes
|
|
262
|
+
- When both are specified for a model, `only_attributes` is applied first, then
|
|
263
|
+
`exclude_attributes`
|
|
264
|
+
- Both narrow down the attributes selected by `attributes`; naming an attribute in
|
|
265
|
+
`only_attributes` does not display it when its kind is not displayed (for example a
|
|
266
|
+
primary key while `attributes` is only `content`)
|
|
267
|
+
- `only_attributes` cannot be set to `true` the way `exclude_attributes` can, because
|
|
268
|
+
"show only all attributes" has no meaning. Use `attributes: false` or
|
|
269
|
+
`exclude_attributes` to hide attributes
|
|
270
|
+
|
|
239
271
|
### Grouping models by namespace
|
|
240
272
|
|
|
241
273
|
Use `cluster: true` to visually group models by their Ruby namespace. This is
|
data/lib/rails_erd/cli.rb
CHANGED
|
@@ -47,6 +47,11 @@ Choice.options do
|
|
|
47
47
|
desc "Display polymorphic and abstract entities."
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
+
option :no_recursive do
|
|
51
|
+
long "--no-recursive"
|
|
52
|
+
desc "Omit self-referential relationships (an entity related to itself)."
|
|
53
|
+
end
|
|
54
|
+
|
|
50
55
|
option :no_indirect do
|
|
51
56
|
long "--direct"
|
|
52
57
|
desc "Omit indirect relationships (through other entities)."
|
|
@@ -72,6 +77,11 @@ Choice.options do
|
|
|
72
77
|
desc "Filter to exclude listed models in diagram."
|
|
73
78
|
end
|
|
74
79
|
|
|
80
|
+
option :only_attributes do
|
|
81
|
+
long "--only_attributes=MODEL.ATTRIBUTE,..."
|
|
82
|
+
desc "Show only the listed attributes for a model, e.g. Book.title,Book.isbn. Models that are not listed keep all their attributes."
|
|
83
|
+
end
|
|
84
|
+
|
|
75
85
|
option :exclude_attributes do
|
|
76
86
|
long "--exclude_attributes=MODEL[.ATTRIBUTE],..."
|
|
77
87
|
desc "Hide attributes per model. Use Model to hide all its attributes or Model.attribute to hide one, e.g. BigTable,User.password_digest."
|
data/lib/rails_erd/config.rb
CHANGED
|
@@ -73,6 +73,11 @@ module RailsERD
|
|
|
73
73
|
when :only, :exclude
|
|
74
74
|
Array(value).join(",").split(",").map { |v| v.strip }
|
|
75
75
|
|
|
76
|
+
# nil | { <string> => [<string>] }
|
|
77
|
+
when :only_attributes
|
|
78
|
+
require "rails_erd/diagram"
|
|
79
|
+
RailsERD::Diagram.normalize_only_attributes(value)
|
|
80
|
+
|
|
76
81
|
# nil | { <string> => true | [<string>] }
|
|
77
82
|
when :exclude_attributes
|
|
78
83
|
require "rails_erd/diagram"
|
|
@@ -80,7 +85,7 @@ module RailsERD
|
|
|
80
85
|
|
|
81
86
|
# true | false
|
|
82
87
|
when :disconnected, :indirect, :inheritance, :markup, :polymorphism,
|
|
83
|
-
:warn, :cluster
|
|
88
|
+
:recursive, :warn, :cluster
|
|
84
89
|
!!value
|
|
85
90
|
|
|
86
91
|
# nil | <string>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "rails_erd/diagram"
|
|
4
4
|
require "erb"
|
|
5
|
+
require "set"
|
|
5
6
|
|
|
6
7
|
module RailsERD
|
|
7
8
|
class Diagram
|
|
@@ -11,6 +12,7 @@ module RailsERD
|
|
|
11
12
|
|
|
12
13
|
setup do
|
|
13
14
|
self.graph = [diagram_type]
|
|
15
|
+
@drawn_entity_names = Set.new
|
|
14
16
|
|
|
15
17
|
# Respect orientation option: horizontal = TB (top-down), vertical = LR (left-right)
|
|
16
18
|
direction = (options.orientation.to_s == "vertical") ? "LR" : "TB"
|
|
@@ -28,6 +30,7 @@ module RailsERD
|
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
each_entity do |entity, attributes|
|
|
33
|
+
@drawn_entity_names << entity.name.to_s
|
|
31
34
|
if er_diagram?
|
|
32
35
|
# Build entity block as a single string to avoid uniq issues with closing braces
|
|
33
36
|
quoted_entity = quote_entity_name(entity)
|
|
@@ -79,27 +82,9 @@ module RailsERD
|
|
|
79
82
|
from, to = relationship.source, relationship.destination
|
|
80
83
|
next unless from && to
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
from.children.each do |child|
|
|
86
|
-
graph << "\t#{quote_entity_name(child.name)} #{er_relation_notation(relationship)} #{quote_entity_name(to.name)} : \"\""
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
to.children.each do |child|
|
|
90
|
-
graph << "\t#{quote_entity_name(from.name)} #{er_relation_notation(relationship)} #{quote_entity_name(child.name)} : \"\""
|
|
91
|
-
end
|
|
92
|
-
else
|
|
93
|
-
graph << "\t`#{from.name}` #{relation_arrow(relationship)} `#{to.name}`"
|
|
94
|
-
|
|
95
|
-
from.children.each do |child|
|
|
96
|
-
graph << "\t`#{child.name}` #{relation_arrow(relationship)} `#{to.name}`"
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
to.children.each do |child|
|
|
100
|
-
graph << "\t`#{from.name}` #{relation_arrow(relationship)} `#{child.name}`"
|
|
101
|
-
end
|
|
102
|
-
end
|
|
85
|
+
draw_relation(from, to, relationship)
|
|
86
|
+
from.children.each { |child| draw_relation(child, to, relationship) }
|
|
87
|
+
to.children.each { |child| draw_relation(from, child, relationship) }
|
|
103
88
|
end
|
|
104
89
|
|
|
105
90
|
save do
|
|
@@ -127,6 +112,22 @@ module RailsERD
|
|
|
127
112
|
options[:mermaid_style] == :erdiagram || options[:mermaid_style] == :er
|
|
128
113
|
end
|
|
129
114
|
|
|
115
|
+
# Mermaid renders any entity a relationship names, so an edge to an entity that was
|
|
116
|
+
# filtered out would draw it back into the diagram. Skip those, as Graphviz already does.
|
|
117
|
+
def draw_relation(from, to, relationship)
|
|
118
|
+
return unless entity_drawn?(from.name) && entity_drawn?(to.name)
|
|
119
|
+
|
|
120
|
+
graph << if er_diagram?
|
|
121
|
+
"\t#{quote_entity_name(from.name)} #{er_relation_notation(relationship)} #{quote_entity_name(to.name)} : \"\""
|
|
122
|
+
else
|
|
123
|
+
"\t`#{from.name}` #{relation_arrow(relationship)} `#{to.name}`"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def entity_drawn?(name)
|
|
128
|
+
@drawn_entity_names.include?(name.to_s)
|
|
129
|
+
end
|
|
130
|
+
|
|
130
131
|
# Quote entity names that contain special characters (like :: for namespaces)
|
|
131
132
|
# Mermaid erDiagram requires double quotes for names with special characters
|
|
132
133
|
def quote_entity_name(name)
|
data/lib/rails_erd/diagram.rb
CHANGED
|
@@ -55,6 +55,14 @@ module RailsERD
|
|
|
55
55
|
# attributes:: Selects which attributes to display. Can be any combination of
|
|
56
56
|
# +:content+, +:primary_keys+, +:foreign_keys+, +:timestamps+, or
|
|
57
57
|
# +:inheritance+.
|
|
58
|
+
# only_attributes:: Shows only the listed attributes for the given models,
|
|
59
|
+
# without affecting other models. Accepts a hash that maps
|
|
60
|
+
# model names to a list of attribute names to keep. From the
|
|
61
|
+
# command line it can also be given as a comma separated
|
|
62
|
+
# string of +Model.attribute+ entries, for example
|
|
63
|
+
# <tt>only_attributes="Book.title,Book.isbn"</tt>. Models
|
|
64
|
+
# that are not listed keep all of their attributes. Unlike
|
|
65
|
+
# +exclude_attributes+ it cannot be set to +true+.
|
|
58
66
|
# exclude_attributes:: Hides attributes on a per-model basis, without affecting
|
|
59
67
|
# other models. Accepts a hash that maps model names to
|
|
60
68
|
# either +true+ (hide all attributes for that model) or a
|
|
@@ -63,6 +71,7 @@ module RailsERD
|
|
|
63
71
|
# entry is either +Model+ (hide all attributes) or
|
|
64
72
|
# +Model.attribute+ (hide a single attribute), for example
|
|
65
73
|
# <tt>exclude_attributes="BigTable,User.password_digest"</tt>.
|
|
74
|
+
# Applied after +only_attributes+.
|
|
66
75
|
# disconnected:: Set to +false+ to exclude entities that are not connected to other
|
|
67
76
|
# entities. Defaults to +false+.
|
|
68
77
|
# indirect:: Set to +false+ to exclude relationships that are indirect.
|
|
@@ -84,21 +93,26 @@ module RailsERD
|
|
|
84
93
|
new(Domain.generate(options), options).create
|
|
85
94
|
end
|
|
86
95
|
|
|
87
|
-
# Canonicalises
|
|
88
|
-
# model names (as strings) to
|
|
89
|
-
#
|
|
96
|
+
# Canonicalises an attribute filter option (+only_attributes+ or
|
|
97
|
+
# +exclude_attributes+) into a hash that maps model names (as strings) to
|
|
98
|
+
# either +true+ (the whole model was named, without any attribute) or an
|
|
99
|
+
# array of attribute names. Accepts several input shapes:
|
|
90
100
|
#
|
|
91
101
|
# * a hash, e.g. <tt>{ "BigTable" => true, "User" => ["password_digest"] }</tt>
|
|
92
|
-
# (values may be +true+/+"all"+ to
|
|
93
|
-
# to
|
|
102
|
+
# (values may be +true+/+"all"+ to name the whole model, +false+/+nil+
|
|
103
|
+
# to name no attributes, or a comma separated string / array of names);
|
|
94
104
|
# * a string or array of <tt>Model</tt> / <tt>Model.attribute</tt>
|
|
95
105
|
# entries, e.g. <tt>"BigTable,User.password_digest"</tt>.
|
|
96
|
-
|
|
106
|
+
#
|
|
107
|
+
# How +true+ and an empty list are interpreted is up to the caller: for
|
|
108
|
+
# +exclude_attributes+ they mean "hide every attribute" and "hide none",
|
|
109
|
+
# for +only_attributes+ they both mean "keep every attribute".
|
|
110
|
+
def normalize_attribute_filter(value)
|
|
97
111
|
return {} if value.nil? || value == false
|
|
98
112
|
|
|
99
113
|
if value.is_a?(Hash)
|
|
100
114
|
value.each_with_object({}) do |(model, attrs), result|
|
|
101
|
-
result[model.to_s] =
|
|
115
|
+
result[model.to_s] = normalize_attribute_filter_value(attrs)
|
|
102
116
|
end
|
|
103
117
|
else
|
|
104
118
|
entries = Array(value).flat_map { |entry| entry.to_s.split(",") }
|
|
@@ -116,6 +130,25 @@ module RailsERD
|
|
|
116
130
|
end
|
|
117
131
|
end
|
|
118
132
|
|
|
133
|
+
# Canonicalises the +only_attributes+ option. See #normalize_attribute_filter.
|
|
134
|
+
# Unlike +exclude_attributes+ it cannot be enabled with a bare +true+:
|
|
135
|
+
# "show only all attributes" has no meaning, so it is rejected rather than
|
|
136
|
+
# silently ignored.
|
|
137
|
+
def normalize_only_attributes(value)
|
|
138
|
+
if value == true
|
|
139
|
+
raise ArgumentError, "only_attributes cannot be true: it takes the attributes to keep, " \
|
|
140
|
+
"either as a hash of model names to attribute names, or as a list of Model.attribute " \
|
|
141
|
+
"entries. Use attributes: false or exclude_attributes to hide attributes."
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
normalize_attribute_filter(value)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Canonicalises the +exclude_attributes+ option. See #normalize_attribute_filter.
|
|
148
|
+
def normalize_exclude_attributes(value)
|
|
149
|
+
normalize_attribute_filter(value)
|
|
150
|
+
end
|
|
151
|
+
|
|
119
152
|
protected
|
|
120
153
|
|
|
121
154
|
def setup(&block)
|
|
@@ -144,7 +177,7 @@ module RailsERD
|
|
|
144
177
|
@callbacks ||= Hash.new { proc {} }
|
|
145
178
|
end
|
|
146
179
|
|
|
147
|
-
def
|
|
180
|
+
def normalize_attribute_filter_value(attrs)
|
|
148
181
|
case attrs
|
|
149
182
|
when true then true
|
|
150
183
|
when false, nil then []
|
|
@@ -243,6 +276,7 @@ module RailsERD
|
|
|
243
276
|
def filtered_relationships
|
|
244
277
|
@domain.relationships.reject { |relationship|
|
|
245
278
|
(!options.indirect && relationship.indirect?) ||
|
|
279
|
+
(!options.recursive && relationship.recursive?) ||
|
|
246
280
|
# Drop relationships to a model removed by :only/:exclude, otherwise the filtered-out
|
|
247
281
|
# model leaks back in: Graphviz skips such edges implicitly (it only draws an edge when
|
|
248
282
|
# both nodes exist) but Mermaid emits every relationship and renders any named entity.
|
|
@@ -318,7 +352,12 @@ module RailsERD
|
|
|
318
352
|
excluded = excluded_attributes_for(entity)
|
|
319
353
|
return [] if excluded == :all
|
|
320
354
|
|
|
355
|
+
only = only_attributes_for(entity)
|
|
356
|
+
|
|
321
357
|
entity.attributes.select { |attribute|
|
|
358
|
+
# Keep only the attributes listed for this specific model, mirroring how
|
|
359
|
+
# :only is applied before :exclude when filtering entities.
|
|
360
|
+
next false if only != :all && !only.include?(attribute.name)
|
|
322
361
|
# Hide attributes excluded for this specific model.
|
|
323
362
|
next false if excluded.include?(attribute.name)
|
|
324
363
|
# Hide every attribute when the :attributes option is off or the entity
|
|
@@ -329,6 +368,18 @@ module RailsERD
|
|
|
329
368
|
}
|
|
330
369
|
end
|
|
331
370
|
|
|
371
|
+
# Returns the attributes the given entity is restricted to through the
|
|
372
|
+
# +only_attributes+ option. Returns +:all+ when no restriction applies,
|
|
373
|
+
# which is the case when the model is not listed at all, or is listed
|
|
374
|
+
# without naming any attribute.
|
|
375
|
+
def only_attributes_for(entity)
|
|
376
|
+
spec = normalized_only_attributes[entity.name]
|
|
377
|
+
return :all if spec.nil? || spec == true
|
|
378
|
+
|
|
379
|
+
names = Array(spec)
|
|
380
|
+
names.empty? ? :all : names
|
|
381
|
+
end
|
|
382
|
+
|
|
332
383
|
# Returns the attribute exclusions configured for the given entity through
|
|
333
384
|
# the +exclude_attributes+ option. Returns +:all+ when every attribute
|
|
334
385
|
# should be hidden, or an array of attribute names otherwise.
|
|
@@ -338,6 +389,10 @@ module RailsERD
|
|
|
338
389
|
Array(spec)
|
|
339
390
|
end
|
|
340
391
|
|
|
392
|
+
def normalized_only_attributes
|
|
393
|
+
@normalized_only_attributes ||= self.class.normalize_only_attributes(options.only_attributes)
|
|
394
|
+
end
|
|
395
|
+
|
|
341
396
|
def normalized_exclude_attributes
|
|
342
397
|
@normalized_exclude_attributes ||= self.class.normalize_exclude_attributes(options.exclude_attributes)
|
|
343
398
|
end
|
data/lib/rails_erd/version.rb
CHANGED
data/lib/rails_erd.rb
CHANGED
|
@@ -51,12 +51,14 @@ module RailsERD
|
|
|
51
51
|
:notation, :simple,
|
|
52
52
|
:orientation, :horizontal,
|
|
53
53
|
:polymorphism, false,
|
|
54
|
+
:recursive, true,
|
|
54
55
|
:sort, true,
|
|
55
56
|
:warn, true,
|
|
56
57
|
:title, true,
|
|
57
58
|
:exclude, nil,
|
|
58
59
|
:exclude_attributes, nil,
|
|
59
60
|
:only, nil,
|
|
61
|
+
:only_attributes, nil,
|
|
60
62
|
:only_recursion_depth, nil,
|
|
61
63
|
:prepend_primary, false,
|
|
62
64
|
:cluster, false,
|
data/test/test_helper.rb
CHANGED
data/test/unit/config_test.rb
CHANGED
|
@@ -133,6 +133,17 @@ class ConfigTest < ActiveSupport::TestCase
|
|
|
133
133
|
assert_equal expected, normalize_value(:exclude_attributes, "BigTable,User.password_digest")
|
|
134
134
|
end
|
|
135
135
|
|
|
136
|
+
test "normalize_value should canonicalize a hash when key is :only_attributes." do
|
|
137
|
+
value = { "Book" => ["title", "isbn"] }
|
|
138
|
+
expected = { "Book" => ["title", "isbn"] }
|
|
139
|
+
assert_equal expected, normalize_value(:only_attributes, value)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
test "normalize_value should parse a string when key is :only_attributes." do
|
|
143
|
+
expected = { "Book" => ["title", "isbn"] }
|
|
144
|
+
assert_equal expected, normalize_value(:only_attributes, "Book.title,Book.isbn")
|
|
145
|
+
end
|
|
146
|
+
|
|
136
147
|
test "normalize_value should return hash with symbol keys when key is :fonts and value is a hash." do
|
|
137
148
|
fonts_value = { "normal" => "Arial", "bold" => "Arial Bold", "italic" => "Arial Italic" }
|
|
138
149
|
expected = {:normal => "Arial", :bold => "Arial Bold", :italic => "Arial Italic"}
|
data/test/unit/diagram_test.rb
CHANGED
|
@@ -323,6 +323,20 @@ class DiagramTest < ActiveSupport::TestCase
|
|
|
323
323
|
assert_equal [false, false], retrieve_relationships(:indirect => false).map(&:indirect?)
|
|
324
324
|
end
|
|
325
325
|
|
|
326
|
+
test "generate should yield self referential relationships if recursive is true" do
|
|
327
|
+
create_model "Node", :parent => :references do
|
|
328
|
+
belongs_to :parent, :class_name => "Node"
|
|
329
|
+
end
|
|
330
|
+
assert_equal [true], retrieve_relationships(:recursive => true).map(&:recursive?)
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
test "generate should filter self referential relationships if recursive is false" do
|
|
334
|
+
create_model "Node", :parent => :references do
|
|
335
|
+
belongs_to :parent, :class_name => "Node"
|
|
336
|
+
end
|
|
337
|
+
assert_equal [], retrieve_relationships(:recursive => false)
|
|
338
|
+
end
|
|
339
|
+
|
|
326
340
|
test "generate should yield relationships from specialized entities" do
|
|
327
341
|
create_model "Foo", :bar => :references
|
|
328
342
|
create_model "Bar", :type => :string
|
|
@@ -474,6 +488,74 @@ class DiagramTest < ActiveSupport::TestCase
|
|
|
474
488
|
assert_equal [], attribute_lists[Author].map(&:name)
|
|
475
489
|
end
|
|
476
490
|
|
|
491
|
+
test "generate should show only the listed attributes for a model" do
|
|
492
|
+
create_model "Book", :title => :string, :subtitle => :string, :pages => :integer
|
|
493
|
+
attribute_lists = retrieve_attribute_lists(:only_attributes => { "Book" => ["title", "pages"] })
|
|
494
|
+
assert_equal %w{pages title}, attribute_lists[Book].map(&:name).sort
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
test "generate should restrict attributes for the listed model only" do
|
|
498
|
+
create_model "Book", :title => :string, :subtitle => :string
|
|
499
|
+
create_model "Author", :name => :string, :born_on => :date
|
|
500
|
+
attribute_lists = retrieve_attribute_lists(:only_attributes => { "Book" => ["title"] })
|
|
501
|
+
assert_equal %w{title}, attribute_lists[Book].map(&:name)
|
|
502
|
+
assert_equal %w{born_on name}, attribute_lists[Author].map(&:name).sort
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
test "generate should accept only_attributes as a string" do
|
|
506
|
+
create_model "Book", :title => :string, :subtitle => :string
|
|
507
|
+
create_model "Author", :name => :string
|
|
508
|
+
attribute_lists = retrieve_attribute_lists(:only_attributes => "Book.title")
|
|
509
|
+
assert_equal %w{title}, attribute_lists[Book].map(&:name)
|
|
510
|
+
assert_equal %w{name}, attribute_lists[Author].map(&:name)
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
test "generate should keep all attributes for a model listed in only_attributes without any attribute" do
|
|
514
|
+
create_model "Book", :title => :string, :subtitle => :string
|
|
515
|
+
attribute_lists = retrieve_attribute_lists(:only_attributes => "Book")
|
|
516
|
+
assert_equal %w{subtitle title}, attribute_lists[Book].map(&:name).sort
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
test "generate should not show attributes selected by only_attributes but rejected by attributes" do
|
|
520
|
+
create_model "Book", :title => :string, :created_at => :datetime
|
|
521
|
+
attribute_lists = retrieve_attribute_lists(:only_attributes => { "Book" => ["title", "created_at"] },
|
|
522
|
+
:attributes => [:content])
|
|
523
|
+
assert_equal %w{title}, attribute_lists[Book].map(&:name)
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
test "generate should apply only_attributes before exclude_attributes" do
|
|
527
|
+
create_model "Book", :title => :string, :subtitle => :string, :pages => :integer
|
|
528
|
+
attribute_lists = retrieve_attribute_lists(:only_attributes => { "Book" => ["title", "subtitle"] },
|
|
529
|
+
:exclude_attributes => { "Book" => ["subtitle"] })
|
|
530
|
+
assert_equal %w{title}, attribute_lists[Book].map(&:name)
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
test "generate should hide all attributes when a model is in both only_attributes and fully excluded" do
|
|
534
|
+
create_model "Book", :title => :string, :subtitle => :string
|
|
535
|
+
attribute_lists = retrieve_attribute_lists(:only_attributes => { "Book" => ["title"] },
|
|
536
|
+
:exclude_attributes => { "Book" => true })
|
|
537
|
+
assert_equal [], attribute_lists[Book].map(&:name)
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
test "normalize_only_attributes should split namespaced models on the first dot only" do
|
|
541
|
+
assert_equal({ "Admin::User" => ["email"] },
|
|
542
|
+
Diagram.normalize_only_attributes("Admin::User.email"))
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
test "normalize_only_attributes should return an empty hash for nil" do
|
|
546
|
+
assert_equal({}, Diagram.normalize_only_attributes(nil))
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
test "normalize_only_attributes should return an empty hash for false" do
|
|
550
|
+
assert_equal({}, Diagram.normalize_only_attributes(false))
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
test "normalize_only_attributes should raise for true" do
|
|
554
|
+
assert_raises ArgumentError do
|
|
555
|
+
Diagram.normalize_only_attributes(true)
|
|
556
|
+
end
|
|
557
|
+
end
|
|
558
|
+
|
|
477
559
|
test "normalize_exclude_attributes should split namespaced models on the first dot only" do
|
|
478
560
|
assert_equal({ "Admin::User" => ["password_digest"] },
|
|
479
561
|
Diagram.normalize_exclude_attributes("Admin::User.password_digest"))
|
data/test/unit/mermaid_test.rb
CHANGED
|
@@ -188,13 +188,30 @@ class MermaidTest < ActiveSupport::TestCase
|
|
|
188
188
|
"\tclass `Cannon`",
|
|
189
189
|
"\tclass `Galleon`",
|
|
190
190
|
"\tclass `Stronghold`",
|
|
191
|
-
"\t`Defensible` --> `Cannon`",
|
|
192
191
|
"\t`Galleon` --> `Cannon`",
|
|
193
192
|
"\t`Stronghold` --> `Cannon`"
|
|
194
193
|
]
|
|
195
194
|
assert_equal expected, diagram.graph.uniq
|
|
196
195
|
end
|
|
197
196
|
|
|
197
|
+
test "generate should not draw polymorphic entity that is omitted by only" do
|
|
198
|
+
create_model "Cannon", :defensible => :references do
|
|
199
|
+
belongs_to :defensible, :polymorphic => true
|
|
200
|
+
end
|
|
201
|
+
create_model "Galleon" do
|
|
202
|
+
has_many :cannons, :as => :defensible
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
expected = [
|
|
206
|
+
"classDiagram",
|
|
207
|
+
"\tdirection TB",
|
|
208
|
+
"\tclass `Cannon`",
|
|
209
|
+
"\tclass `Galleon`",
|
|
210
|
+
"\t`Galleon` --> `Cannon`"
|
|
211
|
+
]
|
|
212
|
+
assert_equal expected, diagram(:only => %w{Cannon Galleon}).graph.uniq
|
|
213
|
+
end
|
|
214
|
+
|
|
198
215
|
test "generate should support one to many relationships" do
|
|
199
216
|
create_one_to_many_assoc_domain
|
|
200
217
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-erd
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rolf Timmermans
|
|
@@ -52,20 +52,6 @@ dependencies:
|
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: 0.2.0
|
|
55
|
-
- !ruby/object:Gem::Dependency
|
|
56
|
-
name: ostruct
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - ">="
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '0'
|
|
62
|
-
type: :runtime
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - ">="
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '0'
|
|
69
55
|
- !ruby/object:Gem::Dependency
|
|
70
56
|
name: ruby-graphviz
|
|
71
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -95,7 +81,7 @@ dependencies:
|
|
|
95
81
|
- !ruby/object:Gem::Version
|
|
96
82
|
version: '0'
|
|
97
83
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name: pry-
|
|
84
|
+
name: pry-byebug
|
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
|
100
86
|
requirements:
|
|
101
87
|
- - ">="
|