tree_support 0.1.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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +2 -0
  6. data/README.org +471 -0
  7. data/Rakefile +6 -0
  8. data/examples/0100_simple.rb +22 -0
  9. data/examples/0110_embeded_node_class.rb +26 -0
  10. data/examples/0120_graphiz_output_image.rb +6 -0
  11. data/examples/0130_node_class_example.rb +98 -0
  12. data/examples/0140_active_record.rb +81 -0
  13. data/examples/0150_acts_as_tree.rb +101 -0
  14. data/examples/0160_acts_as_tree_and_list.rb +133 -0
  15. data/examples/0170_node_class.rb +28 -0
  16. data/examples/0180_replace_to_active_record_tree.rb +120 -0
  17. data/examples/0190_generate_ruby_code.rb +68 -0
  18. data/examples/0200_ar_tree_model.rb +82 -0
  19. data/examples/0201_safe_destroy_all.rb +55 -0
  20. data/examples/0210_take_drop.rb +40 -0
  21. data/examples/0220_it_will_not_be_strange_to_tojson.rb +27 -0
  22. data/examples/0230_list_to_tree.rb +68 -0
  23. data/examples/0240_memory_record.rb +34 -0
  24. data/examples/Gemfile +12 -0
  25. data/examples/Gemfile.lock +137 -0
  26. data/examples/demo.rb +126 -0
  27. data/images/drop.png +0 -0
  28. data/images/take.png +0 -0
  29. data/images/take_drop.png +0 -0
  30. data/images/tree.png +0 -0
  31. data/images/tree_color.png +0 -0
  32. data/images/tree_label.png +0 -0
  33. data/lib/tree_support/ar_tree_model.rb +74 -0
  34. data/lib/tree_support/graphviz_builder.rb +78 -0
  35. data/lib/tree_support/inspector.rb +116 -0
  36. data/lib/tree_support/node.rb +124 -0
  37. data/lib/tree_support/railtie.rb +9 -0
  38. data/lib/tree_support/tree_support.rb +28 -0
  39. data/lib/tree_support/treeable.rb +52 -0
  40. data/lib/tree_support/version.rb +3 -0
  41. data/lib/tree_support.rb +2 -0
  42. data/spec/ar_tree_model_spec.rb +82 -0
  43. data/spec/node_spec.rb +52 -0
  44. data/spec/spec_helper.rb +8 -0
  45. data/spec/tree_support_spec.rb +28 -0
  46. data/spec/treeable_spec.rb +59 -0
  47. data/tree_support.gemspec +30 -0
  48. metadata +196 -0
@@ -0,0 +1,40 @@
1
+ # -*- coding: utf-8 -*-
2
+ require "bundler/setup"
3
+ require "tree_support"
4
+ puts "--------------------------------------------------------------------------------"
5
+ puts TreeSupport.example.to_s_tree(drop: 3)
6
+ puts "--------------------------------------------------------------------------------"
7
+ puts TreeSupport.example.to_s_tree(take: 3)
8
+ puts "--------------------------------------------------------------------------------"
9
+ puts TreeSupport.example.to_s_tree(take: 3, drop: 1)
10
+ # >> --------------------------------------------------------------------------------
11
+ # >> Shake the sword
12
+ # >> Attack magic
13
+ # >> ├─Summoned Beast X
14
+ # >> └─Summoned Beast Y
15
+ # >> Repel sword in length
16
+ # >> Place a trap
17
+ # >> Shoot a bow and arrow
18
+ # >> Recovery magic
19
+ # >> Drink recovery medicine
20
+ # >> --------------------------------------------------------------------------------
21
+ # >> *root*
22
+ # >> ├─Battle
23
+ # >> │ ├─Attack
24
+ # >> │ └─Defense
25
+ # >> ├─Withdraw
26
+ # >> │ ├─To stop
27
+ # >> │ └─To escape
28
+ # >> └─Break
29
+ # >> ├─Stop
30
+ # >> └─Recover
31
+ # >> --------------------------------------------------------------------------------
32
+ # >> Battle
33
+ # >> ├─Attack
34
+ # >> └─Defense
35
+ # >> Withdraw
36
+ # >> ├─To stop
37
+ # >> └─To escape
38
+ # >> Break
39
+ # >> ├─Stop
40
+ # >> └─Recover
@@ -0,0 +1,27 @@
1
+ # It will not be strange to tojson
2
+ #
3
+ require "bundler/setup"
4
+
5
+ require "rails"
6
+ require "active_record"
7
+ require "tree_support"
8
+ require "byebug"
9
+
10
+ Class.new(Rails::Application){config.eager_load = false}.initialize! # In order to read Railtie
11
+
12
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
13
+ ActiveRecord::Migration.verbose = false
14
+
15
+ ActiveRecord::Schema.define do
16
+ create_table :nodes do |t|
17
+ t.belongs_to :parent
18
+ t.string :name
19
+ end
20
+ end
21
+
22
+ class Node < ActiveRecord::Base
23
+ ar_tree_model
24
+ end
25
+
26
+ Node.create!(name: "*root*")
27
+ Node.first.to_json # => "{\"id\":1,\"parent_id\":null,\"name\":\"*root*\"}"
@@ -0,0 +1,68 @@
1
+ require "bundler/setup"
2
+ require "tree_support"
3
+
4
+ records = [
5
+ {key: :a0, parent: nil},
6
+ {key: :a1, parent: :a0},
7
+ {key: :a2, parent: :a1},
8
+
9
+ {key: :b0, parent: nil},
10
+ {key: :b1, parent: :b0},
11
+ {key: :b2, parent: :b1},
12
+ ]
13
+
14
+ # ---------- Convert with function of library
15
+ if true
16
+ puts TreeSupport.records_to_tree(records).collect(&:to_s_tree)
17
+ puts TreeSupport.records_to_tree(records, root_key: :root).to_s_tree
18
+ end
19
+
20
+ # ---------- How to write by yourself
21
+ if true
22
+ source_hash = records.inject({}) { |a, e| a.merge(e[:key] => e) }
23
+ node_hash = records.inject({}) { |a, e| a.merge(e[:key] => TreeSupport::Node.new(e[:key])) }
24
+ node_hash.each_value { |node|
25
+ if parent = source_hash[node.key][:parent]
26
+ parent_node = node_hash[parent]
27
+ node.parent = parent_node
28
+ parent_node.children << node
29
+ end
30
+ }
31
+ roots = node_hash.each_value.find_all { |e| e.parent == nil }
32
+ puts roots.collect(&:to_s_tree)
33
+
34
+ # When you want to make one route
35
+ root = TreeSupport::Node.new(:root)
36
+ roots.each do |e|
37
+ e.parent = root
38
+ root.children << e
39
+ end
40
+ puts root.to_s_tree
41
+ end
42
+
43
+ # >> a0
44
+ # >> └─a1
45
+ # >> └─a2
46
+ # >> b0
47
+ # >> └─b1
48
+ # >> └─b2
49
+ # >> root
50
+ # >> ├─a0
51
+ # >> │ └─a1
52
+ # >> │ └─a2
53
+ # >> └─b0
54
+ # >> └─b1
55
+ # >> └─b2
56
+ # >> a0
57
+ # >> └─a1
58
+ # >> └─a2
59
+ # >> b0
60
+ # >> └─b1
61
+ # >> └─b2
62
+ # >> root
63
+ # >> ├─a0
64
+ # >> │ └─a1
65
+ # >> │ └─a2
66
+ # >> └─b0
67
+ # >> └─b1
68
+ # >> └─b2
@@ -0,0 +1,34 @@
1
+ # Example of combining with MemoryRecord
2
+ require "bundler/setup"
3
+ require "tree_support"
4
+ require "memory_record"
5
+
6
+ class Foo
7
+ include MemoryRecord
8
+ memory_record [
9
+ {key: :a, name: "A", parent: nil},
10
+ {key: :b, name: "B", parent: :a},
11
+ {key: :c, name: "C", parent: :b},
12
+ ]
13
+
14
+ # Any structure can be used as long as it can respond to parent and children
15
+ concerning :TreeMethods do
16
+ included do
17
+ include TreeSupport::Treeable
18
+ include TreeSupport::Stringify
19
+ end
20
+
21
+ def parent
22
+ self.class[super]
23
+ end
24
+
25
+ def children
26
+ self.class.find_all {|e| e.parent == self }
27
+ end
28
+ end
29
+ end
30
+
31
+ puts Foo.find_all(&:root?).collect(&:to_s_tree)
32
+ # >> A
33
+ # >> └─B
34
+ # >> └─C
data/examples/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "https://rubygems.org"
2
+
3
+ gem "tree_support", :path => ".."
4
+ gem "memory_record"
5
+
6
+ gem "rails"
7
+ gem "activerecord"
8
+ gem "sqlite3"
9
+ gem "gviz"
10
+ gem "acts_as_tree"
11
+ gem "acts_as_list"
12
+ gem "byebug"
@@ -0,0 +1,137 @@
1
+ PATH
2
+ remote: ..
3
+ specs:
4
+ tree_support (0.0.1)
5
+ activesupport
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ actioncable (5.0.0)
11
+ actionpack (= 5.0.0)
12
+ nio4r (~> 1.2)
13
+ websocket-driver (~> 0.6.1)
14
+ actionmailer (5.0.0)
15
+ actionpack (= 5.0.0)
16
+ actionview (= 5.0.0)
17
+ activejob (= 5.0.0)
18
+ mail (~> 2.5, >= 2.5.4)
19
+ rails-dom-testing (~> 2.0)
20
+ actionpack (5.0.0)
21
+ actionview (= 5.0.0)
22
+ activesupport (= 5.0.0)
23
+ rack (~> 2.0)
24
+ rack-test (~> 0.6.3)
25
+ rails-dom-testing (~> 2.0)
26
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
27
+ actionview (5.0.0)
28
+ activesupport (= 5.0.0)
29
+ builder (~> 3.1)
30
+ erubis (~> 2.7.0)
31
+ rails-dom-testing (~> 2.0)
32
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
33
+ activejob (5.0.0)
34
+ activesupport (= 5.0.0)
35
+ globalid (>= 0.3.6)
36
+ activemodel (5.0.0)
37
+ activesupport (= 5.0.0)
38
+ activerecord (5.0.0)
39
+ activemodel (= 5.0.0)
40
+ activesupport (= 5.0.0)
41
+ arel (~> 7.0)
42
+ activesupport (5.0.0)
43
+ concurrent-ruby (~> 1.0, >= 1.0.2)
44
+ i18n (~> 0.7)
45
+ minitest (~> 5.1)
46
+ tzinfo (~> 1.1)
47
+ acts_as_list (0.7.6)
48
+ activerecord (>= 3.0)
49
+ acts_as_tree (2.4.0)
50
+ activerecord (>= 3.0.0)
51
+ arel (7.1.0)
52
+ builder (3.2.2)
53
+ byebug (9.0.5)
54
+ concurrent-ruby (1.0.2)
55
+ erubis (2.7.0)
56
+ globalid (0.3.6)
57
+ activesupport (>= 4.1.0)
58
+ gviz (0.3.5)
59
+ thor
60
+ i18n (0.7.0)
61
+ loofah (2.0.3)
62
+ nokogiri (>= 1.5.9)
63
+ mail (2.6.4)
64
+ mime-types (>= 1.16, < 4)
65
+ memory_record (0.0.6)
66
+ activemodel
67
+ activesupport
68
+ method_source (0.8.2)
69
+ mime-types (3.1)
70
+ mime-types-data (~> 3.2015)
71
+ mime-types-data (3.2016.0521)
72
+ mini_portile2 (2.1.0)
73
+ minitest (5.9.0)
74
+ nio4r (1.2.1)
75
+ nokogiri (1.6.8)
76
+ mini_portile2 (~> 2.1.0)
77
+ pkg-config (~> 1.1.7)
78
+ pkg-config (1.1.7)
79
+ rack (2.0.1)
80
+ rack-test (0.6.3)
81
+ rack (>= 1.0)
82
+ rails (5.0.0)
83
+ actioncable (= 5.0.0)
84
+ actionmailer (= 5.0.0)
85
+ actionpack (= 5.0.0)
86
+ actionview (= 5.0.0)
87
+ activejob (= 5.0.0)
88
+ activemodel (= 5.0.0)
89
+ activerecord (= 5.0.0)
90
+ activesupport (= 5.0.0)
91
+ bundler (>= 1.3.0, < 2.0)
92
+ railties (= 5.0.0)
93
+ sprockets-rails (>= 2.0.0)
94
+ rails-dom-testing (2.0.1)
95
+ activesupport (>= 4.2.0, < 6.0)
96
+ nokogiri (~> 1.6.0)
97
+ rails-html-sanitizer (1.0.3)
98
+ loofah (~> 2.0)
99
+ railties (5.0.0)
100
+ actionpack (= 5.0.0)
101
+ activesupport (= 5.0.0)
102
+ method_source
103
+ rake (>= 0.8.7)
104
+ thor (>= 0.18.1, < 2.0)
105
+ rake (11.2.2)
106
+ sprockets (3.7.0)
107
+ concurrent-ruby (~> 1.0)
108
+ rack (> 1, < 3)
109
+ sprockets-rails (3.1.1)
110
+ actionpack (>= 4.0)
111
+ activesupport (>= 4.0)
112
+ sprockets (>= 3.0.0)
113
+ sqlite3 (1.3.11)
114
+ thor (0.19.1)
115
+ thread_safe (0.3.5)
116
+ tzinfo (1.2.2)
117
+ thread_safe (~> 0.1)
118
+ websocket-driver (0.6.4)
119
+ websocket-extensions (>= 0.1.0)
120
+ websocket-extensions (0.1.2)
121
+
122
+ PLATFORMS
123
+ ruby
124
+
125
+ DEPENDENCIES
126
+ activerecord
127
+ acts_as_list
128
+ acts_as_tree
129
+ byebug
130
+ gviz
131
+ memory_record
132
+ rails
133
+ sqlite3
134
+ tree_support!
135
+
136
+ BUNDLED WITH
137
+ 1.16.0.pre.3
data/examples/demo.rb ADDED
@@ -0,0 +1,126 @@
1
+ # output ../images/*
2
+ require "bundler/setup"
3
+ require "tree_support"
4
+
5
+ root = TreeSupport.example
6
+
7
+ p root.each_node.collect.with_index {|n, i| [n.name, i]}
8
+ puts root.to_s_tree
9
+ puts TreeSupport.tree(root)
10
+ puts TreeSupport.tree(root, drop: 1)
11
+ puts TreeSupport.tree(root, take: 3)
12
+ puts TreeSupport.tree(root, take: 3, drop: 1)
13
+ puts TreeSupport.tree(root) {|node, _locals| node.object_id}
14
+ # TreeSupport.graph_open(root)
15
+
16
+ TreeSupport.graphviz(root) {|node|
17
+ if node.name.include?("Attack")
18
+ {fillcolor: "lightblue", style: "filled"}
19
+ elsif node.name.include?("Recover")
20
+ {fillcolor: "lightpink", style: "filled"}
21
+ end
22
+ }.output("../images/tree_color.png")
23
+
24
+ TreeSupport.graphviz(root) {|node|
25
+ {label: node.name.chars.first}
26
+ }.output("../images/tree_label.png")
27
+
28
+ TreeSupport.graphviz(root).output("../images/tree.png")
29
+ TreeSupport.graphviz(root, take: 3).output("../images/take.png")
30
+ TreeSupport.graphviz(root, drop: 1).output("../images/drop.png")
31
+ TreeSupport.graphviz(root, take: 3, drop: 1).output("../images/take_drop.png")
32
+ # >> [["*root*", 0], ["Battle", 1], ["Attack", 2], ["Shake the sword", 3], ["Attack magic", 4], ["Summoned Beast X", 5], ["Summoned Beast Y", 6], ["Repel sword in length", 7], ["Defense", 8], ["Withdraw", 9], ["To stop", 10], ["Place a trap", 11], ["Shoot a bow and arrow", 12], ["To escape", 13], ["Break", 14], ["Stop", 15], ["Recover", 16], ["Recovery magic", 17], ["Drink recovery medicine", 18]]
33
+ # >> *root*
34
+ # >> ├─Battle
35
+ # >> │ ├─Attack
36
+ # >> │ │ ├─Shake the sword
37
+ # >> │ │ ├─Attack magic
38
+ # >> │ │ │ ├─Summoned Beast X
39
+ # >> │ │ │ └─Summoned Beast Y
40
+ # >> │ │ └─Repel sword in length
41
+ # >> │ └─Defense
42
+ # >> ├─Withdraw
43
+ # >> │ ├─To stop
44
+ # >> │ │ ├─Place a trap
45
+ # >> │ │ └─Shoot a bow and arrow
46
+ # >> │ └─To escape
47
+ # >> └─Break
48
+ # >> ├─Stop
49
+ # >> └─Recover
50
+ # >> ├─Recovery magic
51
+ # >> └─Drink recovery medicine
52
+ # >> *root*
53
+ # >> ├─Battle
54
+ # >> │ ├─Attack
55
+ # >> │ │ ├─Shake the sword
56
+ # >> │ │ ├─Attack magic
57
+ # >> │ │ │ ├─Summoned Beast X
58
+ # >> │ │ │ └─Summoned Beast Y
59
+ # >> │ │ └─Repel sword in length
60
+ # >> │ └─Defense
61
+ # >> ├─Withdraw
62
+ # >> │ ├─To stop
63
+ # >> │ │ ├─Place a trap
64
+ # >> │ │ └─Shoot a bow and arrow
65
+ # >> │ └─To escape
66
+ # >> └─Break
67
+ # >> ├─Stop
68
+ # >> └─Recover
69
+ # >> ├─Recovery magic
70
+ # >> └─Drink recovery medicine
71
+ # >> Battle
72
+ # >> ├─Attack
73
+ # >> │ ├─Shake the sword
74
+ # >> │ ├─Attack magic
75
+ # >> │ │ ├─Summoned Beast X
76
+ # >> │ │ └─Summoned Beast Y
77
+ # >> │ └─Repel sword in length
78
+ # >> └─Defense
79
+ # >> Withdraw
80
+ # >> ├─To stop
81
+ # >> │ ├─Place a trap
82
+ # >> │ └─Shoot a bow and arrow
83
+ # >> └─To escape
84
+ # >> Break
85
+ # >> ├─Stop
86
+ # >> └─Recover
87
+ # >> ├─Recovery magic
88
+ # >> └─Drink recovery medicine
89
+ # >> *root*
90
+ # >> ├─Battle
91
+ # >> │ ├─Attack
92
+ # >> │ └─Defense
93
+ # >> ├─Withdraw
94
+ # >> │ ├─To stop
95
+ # >> │ └─To escape
96
+ # >> └─Break
97
+ # >> ├─Stop
98
+ # >> └─Recover
99
+ # >> Battle
100
+ # >> ├─Attack
101
+ # >> └─Defense
102
+ # >> Withdraw
103
+ # >> ├─To stop
104
+ # >> └─To escape
105
+ # >> Break
106
+ # >> ├─Stop
107
+ # >> └─Recover
108
+ # >> 70279213508120
109
+ # >> ├─70279213507760
110
+ # >> │ ├─70279213507500
111
+ # >> │ │ ├─70279213507240
112
+ # >> │ │ ├─70279213507000
113
+ # >> │ │ │ ├─70279213506800
114
+ # >> │ │ │ └─70279213506660
115
+ # >> │ │ └─70279213507200
116
+ # >> │ └─70279213509960
117
+ # >> ├─70279213498160
118
+ # >> │ ├─70279213497920
119
+ # >> │ │ ├─70279213497740
120
+ # >> │ │ └─70279213497600
121
+ # >> │ └─70279213497380
122
+ # >> └─70279213497180
123
+ # >> ├─70279213496960
124
+ # >> └─70279213496720
125
+ # >> ├─70279213496480
126
+ # >> └─70279213496320
data/images/drop.png ADDED
Binary file
data/images/take.png ADDED
Binary file
Binary file
data/images/tree.png ADDED
Binary file
Binary file
Binary file
@@ -0,0 +1,74 @@
1
+ # acts_as_tree replacement
2
+ #
3
+ # class Node < ActiveRecord::Base
4
+ # ar_tree_model # default
5
+ # ar_tree_model scope: -> { order(:name) } # Designate the scope yourself
6
+ # ar_tree_model scope: -> { order(:id).where(active: true) } # You can also specify where
7
+ # end
8
+ #
9
+ require "active_support/concern"
10
+
11
+ module TreeSupport
12
+ module ArTreeModel
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ end
17
+
18
+ class_methods do
19
+ def ar_tree_model(options = {})
20
+ return if ar_tree_model_defined?
21
+
22
+ class_attribute :ar_tree_model_configuration
23
+ self.ar_tree_model_configuration = {
24
+ scope: -> { order(:id) },
25
+ }.merge(options)
26
+
27
+ if block_given?
28
+ yield ar_tree_model_configuration
29
+ end
30
+
31
+ include SingletonMethods
32
+ end
33
+
34
+ def ar_tree_model_defined?
35
+ ancestors.include?(SingletonMethods)
36
+ end
37
+ end
38
+
39
+ concern :SingletonMethods do
40
+ include Treeable
41
+ include Stringify
42
+
43
+ included do
44
+ scope :tree_default_scope, ar_tree_model_configuration[:scope]
45
+
46
+ belongs_to :parent, -> { tree_default_scope }, class_name: name, foreign_key: :parent_id, required: false
47
+ has_many :children, -> { tree_default_scope }, class_name: name, foreign_key: :parent_id, dependent: :destroy, inverse_of: :parent
48
+ scope :roots, -> { tree_default_scope.where(parent_id: nil) }
49
+ end
50
+
51
+ class_methods do
52
+ def ar_tree_model?
53
+ ar_tree_model_defined? # && columns_hash.has_key?(:id)
54
+ end
55
+
56
+ def root
57
+ roots.first
58
+ end
59
+
60
+ # In combination with acts_as_list accident in destroy_all, we have to erase from the leaves in order
61
+ def safe_destroy_all
62
+ roots.collect(&:destroy)
63
+ end
64
+
65
+ def destroy_all(*args)
66
+ if respond_to?(:acts_as_list)
67
+ ActiveSupport::Deprecation.warn("When you use acts_as_list destroy_all do not get id failed to accidentally delete_all Please use safe_destroy_all to erase from the end")
68
+ end
69
+ super
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,78 @@
1
+ require "gviz"
2
+
3
+ # for GvizEx#output
4
+ require "pathname"
5
+ require "delegate"
6
+ require "fileutils"
7
+
8
+ require "active_support/core_ext/module/delegation"
9
+
10
+ module TreeSupport
11
+ def self.graphviz(*args, &block)
12
+ GraphvizBuilder.build(*args, &block)
13
+ end
14
+
15
+ def self.graph_open(*args, &block)
16
+ graphviz(*args, &block).output("_output.png")
17
+ `open _output.png`
18
+ end
19
+
20
+ class GraphvizBuilder
21
+ # For Gviz#save only for some reason
22
+ class GvizEx < SimpleDelegator
23
+ def output(filename)
24
+ filename = Pathname(filename).expand_path
25
+ FileUtils.makedirs(filename.dirname)
26
+ save("#{filename.dirname}/#{filename.basename(".*")}", filename.extname.delete("."))
27
+ end
28
+
29
+ # alias to_dot to_s can not
30
+ def to_dot
31
+ to_s
32
+ end
33
+ end
34
+
35
+ def self.build(object, *args, &block)
36
+ new(*args, &block).build(object)
37
+ end
38
+
39
+ def initialize(**options, &block)
40
+ @options = {
41
+ take: 256,
42
+ drop: 0,
43
+ }.merge(options)
44
+ @block = block
45
+ end
46
+
47
+ def build(object)
48
+ GvizEx.new(Gviz.new).tap do |gv|
49
+ gv.global(rankdir: "LR", concentrate: "true")
50
+ visit(gv, object)
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def visit(gv, object, depth = 0)
57
+ if depth < @options[:take]
58
+ if @options[:drop] <= depth
59
+ attrs = {}
60
+ if @block
61
+ attrs = @block.call(object) || {}
62
+ end
63
+ attrs[:label] ||= TreeSupport.node_name(object)
64
+ gv.node(node_code(object), attrs)
65
+ if depth.next < @options[:take]
66
+ gv.route node_code(object) => object.children.collect {|node| node_code(node) }
67
+ end
68
+ end
69
+ object.children.each {|e| visit(gv, e, depth.next) }
70
+ end
71
+ end
72
+
73
+ def node_code(object)
74
+ # I do not want to be a symbol because it is not subject to GC, but because I get angry with Gviz it is a symbolic symbol
75
+ :"n#{object.object_id}"
76
+ end
77
+ end
78
+ end