peekdb 0.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.
- data/.gitignore +6 -0
- data/.rvmrc +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +28 -0
- data/README.md +23 -0
- data/Rakefile +8 -0
- data/bin/peekdb +10 -0
- data/lib/peekdb/database.rb +36 -0
- data/lib/peekdb/database_mysql.rb +2 -0
- data/lib/peekdb/database_psql.rb +57 -0
- data/lib/peekdb/database_sqlite.rb +2 -0
- data/lib/peekdb/graph.rb +73 -0
- data/lib/peekdb.rb +97 -0
- data/peekdb.gemspec +21 -0
- data/spec/peekdb/graph_spec.rb +18 -0
- data/spec/spec_helper.rb +2 -0
- metadata +114 -0
data/.rvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
rvm --create ruby-1.9.2-p290@peekdb
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: http://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
diff-lcs (1.1.3)
|
|
5
|
+
pg (0.13.2)
|
|
6
|
+
rspec (2.9.0)
|
|
7
|
+
rspec-core (~> 2.9.0)
|
|
8
|
+
rspec-expectations (~> 2.9.0)
|
|
9
|
+
rspec-mocks (~> 2.9.0)
|
|
10
|
+
rspec-core (2.9.0)
|
|
11
|
+
rspec-expectations (2.9.1)
|
|
12
|
+
diff-lcs (~> 1.1.3)
|
|
13
|
+
rspec-mocks (2.9.0)
|
|
14
|
+
ruby-graphviz (1.0.5)
|
|
15
|
+
shoulda (3.0.1)
|
|
16
|
+
shoulda-context (~> 1.0.0)
|
|
17
|
+
shoulda-matchers (~> 1.0.0)
|
|
18
|
+
shoulda-context (1.0.0)
|
|
19
|
+
shoulda-matchers (1.0.0)
|
|
20
|
+
|
|
21
|
+
PLATFORMS
|
|
22
|
+
ruby
|
|
23
|
+
|
|
24
|
+
DEPENDENCIES
|
|
25
|
+
pg
|
|
26
|
+
rspec
|
|
27
|
+
ruby-graphviz
|
|
28
|
+
shoulda
|
data/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# PeekDB - Database Quick View
|
|
2
|
+
|
|
3
|
+
A command line utility that builds a simple force-directed ER diagram for a database. The output can be .png or .dot formats saved in the current directory. Dot files are great for reuse within Omnigraffle.
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
Installation
|
|
7
|
+
-------
|
|
8
|
+
gem install peek
|
|
9
|
+
|
|
10
|
+
Usage
|
|
11
|
+
-------
|
|
12
|
+
peekdb -n [database-name] -t [psql | mysql | sqlite ] -f [png | dot]
|
|
13
|
+
|
|
14
|
+
Todo
|
|
15
|
+
-------
|
|
16
|
+
* Add support for SQLite and MySQL
|
|
17
|
+
* Add support for extraction of views
|
|
18
|
+
* Add support for extraction of column names
|
|
19
|
+
|
|
20
|
+
License
|
|
21
|
+
-------
|
|
22
|
+
|
|
23
|
+
MIT License. Copyright 2012 Ennova.
|
data/Rakefile
ADDED
data/bin/peekdb
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class Database
|
|
2
|
+
|
|
3
|
+
attr_reader :name, :connection, :tables, :relations
|
|
4
|
+
|
|
5
|
+
def initialize(name)
|
|
6
|
+
@name = name
|
|
7
|
+
|
|
8
|
+
begin
|
|
9
|
+
open_connection(@name)
|
|
10
|
+
puts "... Inspecting database #{@name}"
|
|
11
|
+
|
|
12
|
+
find_tables
|
|
13
|
+
puts "... Found #{@tables.size} tables"
|
|
14
|
+
|
|
15
|
+
find_relations
|
|
16
|
+
puts "... Found #{@relations.size} relations"
|
|
17
|
+
rescue Exception => e
|
|
18
|
+
puts "... Error #{e}"
|
|
19
|
+
exit(1)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def open_connection(database_name)
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find_tables
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def find_relations
|
|
34
|
+
raise NotImplementedError
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
class DatabasePSQL < Database
|
|
2
|
+
|
|
3
|
+
attr_reader :name, :connection, :tables, :relations
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
def open_connection(database_name)
|
|
8
|
+
@connection = PGconn.open(:dbname => @name)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# Reference from PostgreSQL:
|
|
12
|
+
# \d information_schema.tables
|
|
13
|
+
# Column | Type | Modifiers
|
|
14
|
+
# -----------------------------+-----------------------------------+-----------
|
|
15
|
+
# table_catalog | information_schema.sql_identifier |
|
|
16
|
+
# table_schema | information_schema.sql_identifier |
|
|
17
|
+
# table_name | information_schema.sql_identifier |
|
|
18
|
+
# table_type | information_schema.character_data |
|
|
19
|
+
# self_referencing_column_name | information_schema.sql_identifier |
|
|
20
|
+
# reference_generation | information_schema.character_data |
|
|
21
|
+
# user_defined_type_catalog | information_schema.sql_identifier |
|
|
22
|
+
# user_defined_type_schema | information_schema.sql_identifier |
|
|
23
|
+
# user_defined_type_name | information_schema.sql_identifier |
|
|
24
|
+
# is_insertable_into | information_schema.yes_or_no |
|
|
25
|
+
# is_typed | information_schema.yes_or_no |
|
|
26
|
+
# commit_action | information_schema.character_data |
|
|
27
|
+
def find_tables
|
|
28
|
+
sql = <<-eos
|
|
29
|
+
SELECT table_name
|
|
30
|
+
FROM information_schema.tables
|
|
31
|
+
WHERE table_type = 'BASE TABLE'
|
|
32
|
+
AND table_schema = 'public'
|
|
33
|
+
eos
|
|
34
|
+
@tables = @connection.exec(sql).values.flatten
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Reference from PostgreSQL:
|
|
38
|
+
# [0] constraint_name
|
|
39
|
+
# [1] table_name
|
|
40
|
+
# [2] column_name
|
|
41
|
+
# [3] foreign_table_name
|
|
42
|
+
# [4] foreign_column_name
|
|
43
|
+
def find_relations
|
|
44
|
+
sql = <<-eos
|
|
45
|
+
SELECT
|
|
46
|
+
tc.constraint_name, tc.table_name, kcu.column_name,
|
|
47
|
+
ccu.table_name AS foreign_table_name,
|
|
48
|
+
ccu.column_name AS foreign_column_name
|
|
49
|
+
FROM
|
|
50
|
+
information_schema.table_constraints AS tc
|
|
51
|
+
JOIN information_schema.key_column_usage AS kcu ON tc.constraint_name = kcu.constraint_name
|
|
52
|
+
JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name
|
|
53
|
+
WHERE constraint_type = 'FOREIGN KEY'
|
|
54
|
+
eos
|
|
55
|
+
@relations = @connection.exec(sql).values
|
|
56
|
+
end
|
|
57
|
+
end
|
data/lib/peekdb/graph.rb
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
class Graph
|
|
2
|
+
|
|
3
|
+
attr_reader :dwg
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@dwg = GraphViz.new(:G, :type => :digraph)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def build(name, tables, relations)
|
|
10
|
+
config_graph(name)
|
|
11
|
+
config_nodes
|
|
12
|
+
config_edges
|
|
13
|
+
|
|
14
|
+
tables.each do |table|
|
|
15
|
+
@dwg.add_nodes(table)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
relations.each do |relation|
|
|
19
|
+
@dwg.add_edges(relation[3], relation[1])
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def output(name, format)
|
|
24
|
+
case format
|
|
25
|
+
when :pdf, nil
|
|
26
|
+
filename = "#{name}.pdf"
|
|
27
|
+
@dwg.output(:pdf => "#{filename}")
|
|
28
|
+
puts "... Writing output #{filename}"
|
|
29
|
+
when :dot
|
|
30
|
+
filename = "#{name}.dot"
|
|
31
|
+
@dwg.output(:dot => filename)
|
|
32
|
+
puts "... Writing output #{filename}"
|
|
33
|
+
else
|
|
34
|
+
raise ArgumentError.new("Unknown output format #{format}")
|
|
35
|
+
exit(1)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def config_graph(name)
|
|
42
|
+
title = name.split('_').each{|s| s.capitalize!}.join(' ')
|
|
43
|
+
date = Time.now
|
|
44
|
+
@dwg.graph[:labelloc] = "t"
|
|
45
|
+
@dwg.graph[:label] = "#{title} Database\nGenerated #{date}"
|
|
46
|
+
@dwg.graph[:fontname] = "Helvetica"
|
|
47
|
+
@dwg.graph[:fontcolor] = "#666666"
|
|
48
|
+
@dwg.graph[:fontsize] = "24"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def config_nodes
|
|
52
|
+
@dwg.node[:color] = "#222222"
|
|
53
|
+
@dwg.node[:style] = "filled"
|
|
54
|
+
@dwg.node[:shape] = "box"
|
|
55
|
+
@dwg.node[:penwidth] = "1"
|
|
56
|
+
@dwg.node[:fontname] = "Helvetica"
|
|
57
|
+
@dwg.node[:fillcolor] = "#eeeeee"
|
|
58
|
+
@dwg.node[:fontcolor] = "#333333"
|
|
59
|
+
@dwg.node[:margin] = "0.05"
|
|
60
|
+
@dwg.node[:fontsize] = "12"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def config_edges
|
|
64
|
+
@dwg.edge[:color] = "#666666"
|
|
65
|
+
@dwg.edge[:weight] = "1"
|
|
66
|
+
@dwg.edge[:fontsize] = "10"
|
|
67
|
+
@dwg.edge[:fontcolor] = "#444444"
|
|
68
|
+
@dwg.edge[:fontname] = "Helvetica"
|
|
69
|
+
@dwg.edge[:dir] = "forward"
|
|
70
|
+
@dwg.edge[:arrowsize] = "0.5"
|
|
71
|
+
@dwg.edge[:arrowhead] = "crow"
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/peekdb.rb
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
require 'pg'
|
|
2
|
+
require 'graphviz'
|
|
3
|
+
require 'optparse'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
require 'pry'
|
|
6
|
+
|
|
7
|
+
require_relative 'peekdb/graph'
|
|
8
|
+
require_relative 'peekdb/database'
|
|
9
|
+
require_relative 'peekdb/database_psql'
|
|
10
|
+
require_relative 'peekdb/database_mysql'
|
|
11
|
+
require_relative 'peekdb/database_sqlite'
|
|
12
|
+
|
|
13
|
+
class PeekDB
|
|
14
|
+
|
|
15
|
+
def initialize(argv)
|
|
16
|
+
puts "PeekDB:"
|
|
17
|
+
begin
|
|
18
|
+
parse_options(argv)
|
|
19
|
+
rescue Exception => e
|
|
20
|
+
puts "... Error FATAL: #{e}"
|
|
21
|
+
exit(1)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def parse_options(args)
|
|
26
|
+
@options = OpenStruct.new
|
|
27
|
+
|
|
28
|
+
opts = OptionParser.new do |opts|
|
|
29
|
+
opts.banner = "Usage: peekdb [options]"
|
|
30
|
+
opts.program_name = "PeekDB"
|
|
31
|
+
opts.separator ""
|
|
32
|
+
opts.separator "Specific options:"
|
|
33
|
+
|
|
34
|
+
opts.on("-n", "--name NAME", "Name of database - required") do |name|
|
|
35
|
+
@options.name = name
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
opts.on("-t", "--type [TYPE]", [:psql, :mysql, :sqlite], "Type of database (psql, mysql, sqlite) - required") do |type|
|
|
39
|
+
@options.type = type
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
opts.on("-f", "--format [FORMAT]", [:pdf, :dot], "Format of output file (pdf, dot) - default pdf") do |format|
|
|
43
|
+
@options.format = format
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
opts.parse!(args)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def run
|
|
50
|
+
if @options.name && @options.name
|
|
51
|
+
case @options.type
|
|
52
|
+
when :psql
|
|
53
|
+
db = DatabasePSQL.new @options.name
|
|
54
|
+
when :mysql
|
|
55
|
+
db = DatabaseMySQL.new @options.name
|
|
56
|
+
when :sqlite
|
|
57
|
+
db = DatabaseSQLite.new @options.name
|
|
58
|
+
else
|
|
59
|
+
puts "... Error FATAL: Unknown database type #{@options.type}"
|
|
60
|
+
exit(1)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
graph = Graph.new
|
|
64
|
+
graph.build(db.name, db.tables, db.relations)
|
|
65
|
+
graph.output(db.name, @options.format)
|
|
66
|
+
else
|
|
67
|
+
puts '... Error FATAL: missing arguments'
|
|
68
|
+
exit(1)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.usage
|
|
73
|
+
puts <<-EOT
|
|
74
|
+
Usage: rails COMMAND [ARGS]
|
|
75
|
+
|
|
76
|
+
The most common rails commands are:
|
|
77
|
+
generate Generate new code (short-cut alias: "g")
|
|
78
|
+
console Start the Rails console (short-cut alias: "c")
|
|
79
|
+
server Start the Rails server (short-cut alias: "s")
|
|
80
|
+
dbconsole Start a console for the database specified in config/database.yml
|
|
81
|
+
(short-cut alias: "db")
|
|
82
|
+
new Create a new Rails application. "rails new my_app" creates a
|
|
83
|
+
new application called MyApp in "./my_app"
|
|
84
|
+
|
|
85
|
+
In addition to those, there are:
|
|
86
|
+
application Generate the Rails application code
|
|
87
|
+
destroy Undo code generated with "generate" (short-cut alias: "d")
|
|
88
|
+
benchmarker See how fast a piece of code runs
|
|
89
|
+
profiler Get profile information from a piece of code
|
|
90
|
+
plugin new Generates skeleton for developing a Rails plugin
|
|
91
|
+
runner Run a piece of code in the application environment (short-cut alias: "r")
|
|
92
|
+
|
|
93
|
+
All commands can be run with -h (or --help) for more information.
|
|
94
|
+
EOT
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
end
|
data/peekdb.gemspec
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Gem::Specification.new do |gem|
|
|
2
|
+
gem.name = "peekdb"
|
|
3
|
+
gem.version = "0.2.0"
|
|
4
|
+
gem.platform = Gem::Platform::RUBY
|
|
5
|
+
gem.authors = ["Adrian Smith"]
|
|
6
|
+
gem.email = ["adrian.smith@ennova.com.au"]
|
|
7
|
+
gem.homepage = "https://github.com/AdrianSmith/peekdb"
|
|
8
|
+
gem.summary = %q{PeekDB generates a quick view of the tables and relationships in a database}
|
|
9
|
+
gem.description = %q{PeekDB is a command line utility that builds a simple force-directed ER diagram for a database. The output can be .png or .dot formats.}
|
|
10
|
+
gem.license = 'MIT'
|
|
11
|
+
|
|
12
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
13
|
+
gem.files = `git ls-files`.split("\n")
|
|
14
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
15
|
+
|
|
16
|
+
gem.add_dependency 'ruby-graphviz'
|
|
17
|
+
gem.add_dependency 'pg'
|
|
18
|
+
|
|
19
|
+
gem.add_development_dependency 'rake'
|
|
20
|
+
gem.add_development_dependency 'rspec'
|
|
21
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require_relative '../spec_helper.rb'
|
|
2
|
+
|
|
3
|
+
describe Graph do
|
|
4
|
+
before do
|
|
5
|
+
@tables = ['book', 'author', 'format']
|
|
6
|
+
@relations = [
|
|
7
|
+
['author-book', 'author', 'id', 'book', 'id'],
|
|
8
|
+
['book-format', 'book', 'id', 'format', 'id']
|
|
9
|
+
]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should create a new graph using database table and relation data" do
|
|
13
|
+
graph = Graph.new
|
|
14
|
+
graph.build('test', @tables, @relations)
|
|
15
|
+
graph.dwg.should be_not_nil
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: peekdb
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
prerelease:
|
|
5
|
+
version: 0.2.0
|
|
6
|
+
platform: ruby
|
|
7
|
+
authors:
|
|
8
|
+
- Adrian Smith
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
|
|
13
|
+
date: 2012-04-29 00:00:00 Z
|
|
14
|
+
dependencies:
|
|
15
|
+
- !ruby/object:Gem::Dependency
|
|
16
|
+
name: ruby-graphviz
|
|
17
|
+
prerelease: false
|
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
19
|
+
none: false
|
|
20
|
+
requirements:
|
|
21
|
+
- - ">="
|
|
22
|
+
- !ruby/object:Gem::Version
|
|
23
|
+
version: "0"
|
|
24
|
+
type: :runtime
|
|
25
|
+
version_requirements: *id001
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: pg
|
|
28
|
+
prerelease: false
|
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
30
|
+
none: false
|
|
31
|
+
requirements:
|
|
32
|
+
- - ">="
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: "0"
|
|
35
|
+
type: :runtime
|
|
36
|
+
version_requirements: *id002
|
|
37
|
+
- !ruby/object:Gem::Dependency
|
|
38
|
+
name: rake
|
|
39
|
+
prerelease: false
|
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: "0"
|
|
46
|
+
type: :development
|
|
47
|
+
version_requirements: *id003
|
|
48
|
+
- !ruby/object:Gem::Dependency
|
|
49
|
+
name: rspec
|
|
50
|
+
prerelease: false
|
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
|
52
|
+
none: false
|
|
53
|
+
requirements:
|
|
54
|
+
- - ">="
|
|
55
|
+
- !ruby/object:Gem::Version
|
|
56
|
+
version: "0"
|
|
57
|
+
type: :development
|
|
58
|
+
version_requirements: *id004
|
|
59
|
+
description: PeekDB is a command line utility that builds a simple force-directed ER diagram for a database. The output can be .png or .dot formats.
|
|
60
|
+
email:
|
|
61
|
+
- adrian.smith@ennova.com.au
|
|
62
|
+
executables:
|
|
63
|
+
- peekdb
|
|
64
|
+
extensions: []
|
|
65
|
+
|
|
66
|
+
extra_rdoc_files: []
|
|
67
|
+
|
|
68
|
+
files:
|
|
69
|
+
- .gitignore
|
|
70
|
+
- .rvmrc
|
|
71
|
+
- Gemfile
|
|
72
|
+
- Gemfile.lock
|
|
73
|
+
- README.md
|
|
74
|
+
- Rakefile
|
|
75
|
+
- bin/peekdb
|
|
76
|
+
- lib/peekdb.rb
|
|
77
|
+
- lib/peekdb/database.rb
|
|
78
|
+
- lib/peekdb/database_mysql.rb
|
|
79
|
+
- lib/peekdb/database_psql.rb
|
|
80
|
+
- lib/peekdb/database_sqlite.rb
|
|
81
|
+
- lib/peekdb/graph.rb
|
|
82
|
+
- peekdb.gemspec
|
|
83
|
+
- spec/peekdb/graph_spec.rb
|
|
84
|
+
- spec/spec_helper.rb
|
|
85
|
+
homepage: https://github.com/AdrianSmith/peekdb
|
|
86
|
+
licenses:
|
|
87
|
+
- MIT
|
|
88
|
+
post_install_message:
|
|
89
|
+
rdoc_options: []
|
|
90
|
+
|
|
91
|
+
require_paths:
|
|
92
|
+
- lib
|
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
|
+
none: false
|
|
95
|
+
requirements:
|
|
96
|
+
- - ">="
|
|
97
|
+
- !ruby/object:Gem::Version
|
|
98
|
+
version: "0"
|
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
|
+
none: false
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: "0"
|
|
105
|
+
requirements: []
|
|
106
|
+
|
|
107
|
+
rubyforge_project:
|
|
108
|
+
rubygems_version: 1.8.23
|
|
109
|
+
signing_key:
|
|
110
|
+
specification_version: 3
|
|
111
|
+
summary: PeekDB generates a quick view of the tables and relationships in a database
|
|
112
|
+
test_files:
|
|
113
|
+
- spec/peekdb/graph_spec.rb
|
|
114
|
+
- spec/spec_helper.rb
|