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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 07a38b05691f97bf85079684c7412bff0bf8b4caf737f52479d2209b3fb2fe5f
4
- data.tar.gz: c8f38108442a38b331cff3b2c0b856584943ac3def5cec0525255c53595e0482
3
+ metadata.gz: e8c66456b4d4e9279e9957ffd932fb244aa160c7f271c67cfafec1217161e232
4
+ data.tar.gz: 70f6317d8e825c273f70495e9eb9f41e4576dea96e4065d8627f45558b5f3cc4
5
5
  SHA512:
6
- metadata.gz: 146e37a81b1f2008f28442f62498822845810a45bb9a5ab1ba35fec8700be809ba2eac95be388a15878e9ff44d7dc5b4abd8b4db8b479871a993a93668d75337
7
- data.tar.gz: 9e5d0c84231120c3e1b804950265a3a6abca1201f46f99bd96b3a0655e46c13bdbb0e7ff0403902f621506de81240818cc7135f92423f8a1be0e50c2468629d2
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."
@@ -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
- if er_diagram?
83
- graph << "\t#{quote_entity_name(from.name)} #{er_relation_notation(relationship)} #{quote_entity_name(to.name)} : \"\""
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)
@@ -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 the +exclude_attributes+ option into a hash that maps
88
- # model names (as strings) to either +true+ (hide all attributes) or an
89
- # array of attribute names to hide. Accepts several input shapes:
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 hide every attribute, +false+/+nil+
93
- # to hide none, or a comma separated string / array of names);
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
- def normalize_exclude_attributes(value)
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] = normalize_exclude_attribute_value(attrs)
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 normalize_exclude_attribute_value(attrs)
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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RailsERD
4
- VERSION = "2.1.0"
4
+ VERSION = "2.2.0"
5
5
  BANNER = "RailsERD #{VERSION}"
6
6
  end
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
@@ -1,7 +1,7 @@
1
1
  require "rubygems"
2
2
  require "bundler/setup"
3
3
  require 'pry'
4
- require 'pry-nav'
4
+ require 'pry-byebug'
5
5
  require 'tmpdir'
6
6
 
7
7
  require "active_record"
@@ -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"}
@@ -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"))
@@ -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.1.0
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-nav
84
+ name: pry-byebug
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
87
  - - ">="