tree_support 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +2 -0
- data/README.org +471 -0
- data/Rakefile +6 -0
- data/examples/0100_simple.rb +22 -0
- data/examples/0110_embeded_node_class.rb +26 -0
- data/examples/0120_graphiz_output_image.rb +6 -0
- data/examples/0130_node_class_example.rb +98 -0
- data/examples/0140_active_record.rb +81 -0
- data/examples/0150_acts_as_tree.rb +101 -0
- data/examples/0160_acts_as_tree_and_list.rb +133 -0
- data/examples/0170_node_class.rb +28 -0
- data/examples/0180_replace_to_active_record_tree.rb +120 -0
- data/examples/0190_generate_ruby_code.rb +68 -0
- data/examples/0200_ar_tree_model.rb +82 -0
- data/examples/0201_safe_destroy_all.rb +55 -0
- data/examples/0210_take_drop.rb +40 -0
- data/examples/0220_it_will_not_be_strange_to_tojson.rb +27 -0
- data/examples/0230_list_to_tree.rb +68 -0
- data/examples/0240_memory_record.rb +34 -0
- data/examples/Gemfile +12 -0
- data/examples/Gemfile.lock +137 -0
- data/examples/demo.rb +126 -0
- data/images/drop.png +0 -0
- data/images/take.png +0 -0
- data/images/take_drop.png +0 -0
- data/images/tree.png +0 -0
- data/images/tree_color.png +0 -0
- data/images/tree_label.png +0 -0
- data/lib/tree_support/ar_tree_model.rb +74 -0
- data/lib/tree_support/graphviz_builder.rb +78 -0
- data/lib/tree_support/inspector.rb +116 -0
- data/lib/tree_support/node.rb +124 -0
- data/lib/tree_support/railtie.rb +9 -0
- data/lib/tree_support/tree_support.rb +28 -0
- data/lib/tree_support/treeable.rb +52 -0
- data/lib/tree_support/version.rb +3 -0
- data/lib/tree_support.rb +2 -0
- data/spec/ar_tree_model_spec.rb +82 -0
- data/spec/node_spec.rb +52 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/tree_support_spec.rb +28 -0
- data/spec/treeable_spec.rb +59 -0
- data/tree_support.gemspec +30 -0
- metadata +196 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
require "kconv"
|
2
|
+
require "active_support/concern"
|
3
|
+
require "active_support/core_ext/module/attribute_accessors" # mattr_accessor
|
4
|
+
|
5
|
+
module TreeSupport
|
6
|
+
mattr_accessor :name_methods
|
7
|
+
self.name_methods = [:to_s_tree_name, :name, :subject, :title]
|
8
|
+
|
9
|
+
def self.tree(*args, &block)
|
10
|
+
Inspector.tree(*args, &block)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.node_name(object)
|
14
|
+
object.send(name_methods.find {|e| object.respond_to?(e)} || :to_s)
|
15
|
+
end
|
16
|
+
|
17
|
+
class Inspector
|
18
|
+
def self.tree(object, *args, &block)
|
19
|
+
new(*args, &block).tree(object)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(**options, &block)
|
23
|
+
@options = {
|
24
|
+
take: 256, # Up to depth N (for when the tree can not be displayed because it is huge)
|
25
|
+
drop: 0, # From the depth N (when set to 1 you can hide the route)
|
26
|
+
root_label: nil, # A valid alternative label for displaying the route
|
27
|
+
tab_space: 4, # Indent width from halfway
|
28
|
+
connect_char: "├",
|
29
|
+
tab_visible_char: "│",
|
30
|
+
edge_char: "└",
|
31
|
+
branch_char: "─",
|
32
|
+
debug: false,
|
33
|
+
}.merge(options)
|
34
|
+
|
35
|
+
@block = block
|
36
|
+
end
|
37
|
+
|
38
|
+
# 木構造の可視化
|
39
|
+
#
|
40
|
+
# 必要なメソッド
|
41
|
+
# parent.children
|
42
|
+
# name
|
43
|
+
#
|
44
|
+
def tree(object, **locals)
|
45
|
+
locals = {
|
46
|
+
depth: [],
|
47
|
+
}.merge(locals)
|
48
|
+
|
49
|
+
if locals[:depth].size > @options[:drop]
|
50
|
+
if object == object.parent.children.last
|
51
|
+
prefix_char = @options[:edge_char]
|
52
|
+
else
|
53
|
+
prefix_char = @options[:connect_char]
|
54
|
+
end
|
55
|
+
else
|
56
|
+
prefix_char = ""
|
57
|
+
end
|
58
|
+
|
59
|
+
indents = locals[:depth].each.with_index.collect {|e, i|
|
60
|
+
if i > @options[:drop]
|
61
|
+
tab = e ? @options[:tab_visible_char] : ""
|
62
|
+
tab.toeuc.ljust(@options[:tab_space]).toutf8
|
63
|
+
end
|
64
|
+
}.join
|
65
|
+
|
66
|
+
if @block
|
67
|
+
label = @block.call(object, locals)
|
68
|
+
else
|
69
|
+
if locals[:depth].empty? && @options[:root_label] # Change if there is root and alternative label
|
70
|
+
label = @options[:root_label]
|
71
|
+
else
|
72
|
+
label = TreeSupport.node_name(object)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
buffer = ""
|
77
|
+
branch_char = nil
|
78
|
+
|
79
|
+
if locals[:depth].size > @options[:drop]
|
80
|
+
branch_char = @options[:branch_char]
|
81
|
+
end
|
82
|
+
if locals[:depth].size < @options[:take]
|
83
|
+
if locals[:depth].size >= @options[:drop]
|
84
|
+
buffer = "#{indents}#{prefix_char}#{branch_char}#{label}#{@options[:debug] ? locals[:depth].inspect : ""}\n"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
flag = false
|
89
|
+
if object.parent
|
90
|
+
flag = (object != object.parent.children.last)
|
91
|
+
end
|
92
|
+
|
93
|
+
locals[:depth].push(flag)
|
94
|
+
if locals[:depth].size < @options[:take]
|
95
|
+
buffer << object.children.collect {|node| tree(node, locals)}.join
|
96
|
+
end
|
97
|
+
locals[:depth].pop
|
98
|
+
|
99
|
+
buffer
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module Stringify
|
104
|
+
def to_s_tree(*args, &block)
|
105
|
+
Inspector.tree(self, *args, &block)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
if $0 == __FILE__
|
111
|
+
$LOAD_PATH << ".."
|
112
|
+
require "tree_support"
|
113
|
+
puts TreeSupport.example.to_s_tree(take: 0)
|
114
|
+
puts TreeSupport.example.to_s_tree(take: 1)
|
115
|
+
puts TreeSupport.example.to_s_tree(take: 2)
|
116
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'active_support/core_ext/module/delegation' # for Module#delegate.
|
2
|
+
|
3
|
+
module TreeSupport
|
4
|
+
# Simple node (because it is troublesome to bother to make it on the application side when only wooden structure information is wanted)
|
5
|
+
class Node
|
6
|
+
include Treeable
|
7
|
+
include Stringify
|
8
|
+
|
9
|
+
attr_accessor :attributes, :parent, :children
|
10
|
+
|
11
|
+
alias_method :name, :attributes
|
12
|
+
alias_method :key, :attributes
|
13
|
+
|
14
|
+
delegate :[], :[]=, :to_h, to: :attributes
|
15
|
+
|
16
|
+
def initialize(attributes = nil, &block)
|
17
|
+
@attributes = attributes
|
18
|
+
@children = []
|
19
|
+
if block_given?
|
20
|
+
instance_eval(&block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def add(*args, &block)
|
25
|
+
tap do
|
26
|
+
children << self.class.new(*args, &block).tap do |v|
|
27
|
+
v.parent = self
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.example
|
34
|
+
Node.new("*root*") do
|
35
|
+
add "Battle" do
|
36
|
+
add "Attack" do
|
37
|
+
add "Shake the sword"
|
38
|
+
add "Attack magic" do
|
39
|
+
add "Summoned Beast X"
|
40
|
+
add "Summoned Beast Y"
|
41
|
+
end
|
42
|
+
add "Repel sword in length"
|
43
|
+
end
|
44
|
+
add "Defense"
|
45
|
+
end
|
46
|
+
add "Withdraw" do
|
47
|
+
add "To stop" do
|
48
|
+
add "Place a trap"
|
49
|
+
add "Shoot a bow and arrow"
|
50
|
+
end
|
51
|
+
add "To escape"
|
52
|
+
end
|
53
|
+
add "Break" do
|
54
|
+
add "Stop"
|
55
|
+
add "Recover" do
|
56
|
+
add "Recovery magic"
|
57
|
+
add "Drink recovery medicine"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Methods for easily making trees from data like CSV
|
64
|
+
class << self
|
65
|
+
# Array -> Tree
|
66
|
+
#
|
67
|
+
# records = [
|
68
|
+
# {key: :a, parent: nil},
|
69
|
+
# {key: :b, parent: :a},
|
70
|
+
# {key: :c, parent: :b},
|
71
|
+
# ]
|
72
|
+
#
|
73
|
+
# puts TreeSupport.records_to_tree(records).to_s_tree
|
74
|
+
# a
|
75
|
+
# └─b
|
76
|
+
# └─c
|
77
|
+
# └─d
|
78
|
+
#
|
79
|
+
# Be sure to have one route
|
80
|
+
#
|
81
|
+
def records_to_tree(records, key: :key, parent_key: :parent, root_key: nil)
|
82
|
+
# Once hashed
|
83
|
+
source_hash = records.inject({}) { |a, e| a.merge(e[key] => e) }
|
84
|
+
# The node also makes it a hash of only the node having the key
|
85
|
+
node_hash = records.inject({}) { |a, e| a.merge(e[key] => Node.new(e[key])) }
|
86
|
+
# Link nodes
|
87
|
+
node_hash.each_value do |node|
|
88
|
+
if parent = source_hash[node.key][parent_key]
|
89
|
+
parent_node = node_hash[parent]
|
90
|
+
node.parent = parent_node
|
91
|
+
parent_node.children << node
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# If the node whose parent was not set is the root (s)
|
96
|
+
roots = node_hash.each_value.find_all {|e| e.parent.nil? }
|
97
|
+
|
98
|
+
# Specify root_key when there are multiple routes and you are in trouble. Then create a new route and hang it.
|
99
|
+
if root_key
|
100
|
+
Node.new(root_key).tap do |root|
|
101
|
+
roots.each do |e|
|
102
|
+
e.parent = root
|
103
|
+
root.children << e
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
roots
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Tree -> Array
|
112
|
+
#
|
113
|
+
# p TreeSupport.tree_to_records(tree)
|
114
|
+
# [
|
115
|
+
# {key: :a, parent: nil},
|
116
|
+
# {key: :b, parent: :a},
|
117
|
+
# {key: :c, parent: :b},
|
118
|
+
# ]
|
119
|
+
#
|
120
|
+
def tree_to_records(root, key: :key, parent_key: :parent)
|
121
|
+
root.each_node.collect {|e| {key => e.key, parent_key => e.parent&.key} }
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Tree structure visualization library
|
2
|
+
#
|
3
|
+
# root = TreeSupport::Node.new("ROOT") do
|
4
|
+
# add "A" do
|
5
|
+
# add "B" do
|
6
|
+
# add "C"
|
7
|
+
# end
|
8
|
+
# end
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# puts TreeSupport.tree(root)
|
12
|
+
# > ROOT
|
13
|
+
# > └─A
|
14
|
+
# > └─B
|
15
|
+
# > └─C
|
16
|
+
|
17
|
+
require "tree_support/treeable"
|
18
|
+
require "tree_support/inspector"
|
19
|
+
require "tree_support/node"
|
20
|
+
require "tree_support/ar_tree_model" if defined?(ActiveRecord)
|
21
|
+
require "tree_support/railtie" if defined?(Rails)
|
22
|
+
|
23
|
+
# Do not put gviz when you do not use it to touch Object
|
24
|
+
begin
|
25
|
+
require "gviz"
|
26
|
+
require "tree_support/graphviz_builder"
|
27
|
+
rescue LoadError
|
28
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Definition of methods that are common in tree-structured interfaces
|
2
|
+
#
|
3
|
+
# All you need is parent and children methods
|
4
|
+
#
|
5
|
+
|
6
|
+
require "active_support/core_ext/module/concerning"
|
7
|
+
|
8
|
+
module TreeSupport
|
9
|
+
concern :Treeable do
|
10
|
+
def root
|
11
|
+
parent ? parent.root : self
|
12
|
+
end
|
13
|
+
|
14
|
+
def root?
|
15
|
+
!parent
|
16
|
+
end
|
17
|
+
|
18
|
+
def leaf?
|
19
|
+
children.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def each_node(&block)
|
23
|
+
return enum_for(__method__) unless block_given?
|
24
|
+
yield self
|
25
|
+
children.each { |e| e.each_node(&block) }
|
26
|
+
end
|
27
|
+
|
28
|
+
def descendants
|
29
|
+
children.flat_map { |e| [e] + e.descendants }
|
30
|
+
end
|
31
|
+
|
32
|
+
def self_and_descendants
|
33
|
+
[self] + descendants
|
34
|
+
end
|
35
|
+
|
36
|
+
def ancestors
|
37
|
+
self_and_ancestors - [self]
|
38
|
+
end
|
39
|
+
|
40
|
+
def self_and_ancestors
|
41
|
+
[self] + (parent ? parent.self_and_ancestors : [])
|
42
|
+
end
|
43
|
+
|
44
|
+
def siblings
|
45
|
+
self_and_siblings - [self]
|
46
|
+
end
|
47
|
+
|
48
|
+
def self_and_siblings
|
49
|
+
parent ? parent.children : []
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/lib/tree_support.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require "rails"
|
4
|
+
require "tree_support/ar_tree_model"
|
5
|
+
require "tree_support/railtie"
|
6
|
+
require "active_record"
|
7
|
+
|
8
|
+
Class.new(Rails::Application){config.eager_load = true}.initialize!
|
9
|
+
|
10
|
+
RSpec.describe "ArTreeModel" do
|
11
|
+
before do
|
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 order: "name"
|
24
|
+
|
25
|
+
def add(name, &block)
|
26
|
+
tap do
|
27
|
+
child = children.create!(name: name)
|
28
|
+
if block_given?
|
29
|
+
child.instance_eval(&block)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
@node = Node.create!(name: "*root*").tap do |n|
|
36
|
+
n.instance_eval do
|
37
|
+
add "Battle" do
|
38
|
+
add "Attack" do
|
39
|
+
add "Shake the sword"
|
40
|
+
add "Attack magic" do
|
41
|
+
add "Summoned Beast X"
|
42
|
+
add "Summoned Beast Y"
|
43
|
+
end
|
44
|
+
add "Repel sword in length"
|
45
|
+
end
|
46
|
+
add "Defense"
|
47
|
+
end
|
48
|
+
add "Withdraw" do
|
49
|
+
add "To stop" do
|
50
|
+
add "Place a trap"
|
51
|
+
add "Shoot a bow and arrow"
|
52
|
+
end
|
53
|
+
add "To escape"
|
54
|
+
end
|
55
|
+
add "Break" do
|
56
|
+
add "Stop"
|
57
|
+
add "Recover" do
|
58
|
+
add "Recovery magic"
|
59
|
+
add "Drink recovery medicine"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "roots" do
|
67
|
+
Node.roots.should == [@node]
|
68
|
+
end
|
69
|
+
|
70
|
+
it "root" do
|
71
|
+
Node.root.should == @node
|
72
|
+
end
|
73
|
+
|
74
|
+
it "to_s_tree" do
|
75
|
+
@node.to_s_tree
|
76
|
+
end
|
77
|
+
|
78
|
+
it "safe_destroy_all" do
|
79
|
+
Node.safe_destroy_all
|
80
|
+
Node.count.should == 0
|
81
|
+
end
|
82
|
+
end
|
data/spec/node_spec.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "Node" do
|
4
|
+
before do
|
5
|
+
@records = [
|
6
|
+
{key: :a0, parent: nil},
|
7
|
+
{key: :a1, parent: :a0},
|
8
|
+
{key: :a2, parent: :a1},
|
9
|
+
{key: :b0, parent: nil},
|
10
|
+
{key: :b1, parent: :b0},
|
11
|
+
{key: :b2, parent: :b1},
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "Array -> Tree(s)" do
|
16
|
+
TreeSupport.records_to_tree(@records).collect(&:to_s_tree).join.should == <<-EOT
|
17
|
+
a0
|
18
|
+
└─a1
|
19
|
+
└─a2
|
20
|
+
b0
|
21
|
+
└─b1
|
22
|
+
└─b2
|
23
|
+
EOT
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
it "Array -> Tree(1)" do
|
28
|
+
TreeSupport.records_to_tree(@records, root_key: :root).to_s_tree.should == <<-EOT
|
29
|
+
root
|
30
|
+
├─a0
|
31
|
+
│ └─a1
|
32
|
+
│ └─a2
|
33
|
+
└─b0
|
34
|
+
└─b1
|
35
|
+
└─b2
|
36
|
+
EOT
|
37
|
+
end
|
38
|
+
|
39
|
+
it "Tree -> Array" do
|
40
|
+
root = TreeSupport.records_to_tree(@records, root_key: :root)
|
41
|
+
records = TreeSupport.tree_to_records(root)
|
42
|
+
records.should == [
|
43
|
+
{key: :root, parent: nil },
|
44
|
+
{key: :a0, parent: :root },
|
45
|
+
{key: :a1, parent: :a0 },
|
46
|
+
{key: :a2, parent: :a1 },
|
47
|
+
{key: :b0, parent: :root },
|
48
|
+
{key: :b1, parent: :b0 },
|
49
|
+
{key: :b2, parent: :b1 },
|
50
|
+
]
|
51
|
+
end
|
52
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "TreeSupport" do
|
4
|
+
it "tree" do
|
5
|
+
expected = <<-EOT
|
6
|
+
*root*
|
7
|
+
├─Battle
|
8
|
+
│ ├─Attack
|
9
|
+
│ │ ├─Shake the sword
|
10
|
+
│ │ ├─Attack magic
|
11
|
+
│ │ │ ├─Summoned Beast X
|
12
|
+
│ │ │ └─Summoned Beast Y
|
13
|
+
│ │ └─Repel sword in length
|
14
|
+
│ └─Defense
|
15
|
+
├─Withdraw
|
16
|
+
│ ├─To stop
|
17
|
+
│ │ ├─Place a trap
|
18
|
+
│ │ └─Shoot a bow and arrow
|
19
|
+
│ └─To escape
|
20
|
+
└─Break
|
21
|
+
├─Stop
|
22
|
+
└─Recover
|
23
|
+
├─Recovery magic
|
24
|
+
└─Drink recovery medicine
|
25
|
+
EOT
|
26
|
+
TreeSupport.example.to_s_tree.should == expected
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
RSpec.describe "Treeable" do
|
4
|
+
before do
|
5
|
+
@root = TreeSupport::Node.new("*root*") do
|
6
|
+
add "a" do
|
7
|
+
add "a1"
|
8
|
+
add "a2" do
|
9
|
+
add "x"
|
10
|
+
end
|
11
|
+
add "a3"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
@a2 = @root.each_node.find {|e| e.name == "a2"}
|
15
|
+
@leaf = @root.each_node.find {|e| e.name == "x"}
|
16
|
+
end
|
17
|
+
|
18
|
+
it "root" do
|
19
|
+
@a2.root.name.should == "*root*"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "root?" do
|
23
|
+
@root.root?.should == true
|
24
|
+
@leaf.root?.should == false
|
25
|
+
end
|
26
|
+
|
27
|
+
it "leaf?" do
|
28
|
+
@root.leaf?.should == false
|
29
|
+
@leaf.leaf?.should == true
|
30
|
+
end
|
31
|
+
|
32
|
+
it "each_node" do
|
33
|
+
@root.each_node.collect(&:name).should == ["*root*", "a", "a1", "a2", "x", "a3"]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "descendants" do
|
37
|
+
@root.descendants.collect(&:name).should == ["a", "a1", "a2", "x", "a3"]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "self_and_descendants" do
|
41
|
+
@root.self_and_descendants.collect(&:name).should == ["*root*", "a", "a1", "a2", "x", "a3"]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "ancestors" do
|
45
|
+
@a2.ancestors.collect(&:name).should == ["a", "*root*"]
|
46
|
+
end
|
47
|
+
|
48
|
+
it "self_and_ancestors" do
|
49
|
+
@a2.self_and_ancestors.collect(&:name).should == ["a2", "a", "*root*"]
|
50
|
+
end
|
51
|
+
|
52
|
+
it "siblings" do
|
53
|
+
@a2.siblings.collect(&:name).should == ["a1", "a3"]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "self_and_siblings" do
|
57
|
+
@a2.self_and_siblings.collect(&:name).should == ["a1", "a2", "a3"]
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tree_support/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "tree_support"
|
8
|
+
s.version = TreeSupport::VERSION
|
9
|
+
s.author = "akicho8"
|
10
|
+
s.email = "akicho8@gmail.com"
|
11
|
+
s.homepage = "https://github.com/akicho8/tree_support"
|
12
|
+
s.summary = "Tree structure visualization function library"
|
13
|
+
s.description = "Tree structure visualization function library"
|
14
|
+
s.platform = Gem::Platform::RUBY
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--charset=UTF-8", "--diagram", "--image-format=jpg"]
|
21
|
+
|
22
|
+
s.add_dependency "activesupport"
|
23
|
+
|
24
|
+
s.add_development_dependency "rake"
|
25
|
+
s.add_development_dependency "rspec"
|
26
|
+
s.add_development_dependency "rails"
|
27
|
+
s.add_development_dependency "activerecord"
|
28
|
+
s.add_development_dependency "sqlite3"
|
29
|
+
s.add_development_dependency "gviz"
|
30
|
+
end
|