schemard 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.
@@ -0,0 +1,56 @@
1
+ module SchemaRD::Utils
2
+ module Singularizer
3
+ def singularize
4
+ return self if NO_SINGULAR_WORDS.include?(self)
5
+
6
+ found = SINGULAR_RULES.find{|regexp, _| self =~ regexp }
7
+ found ? self.gsub(found[0], found[1]) : self
8
+ end
9
+ SINGULAR_RULES = [
10
+ [/(z)ombies$/i, "\\1ombie"],
11
+ [/(z)ombie$/i, "\\1ombie"],
12
+ [/(m)oves$/i, "\\1ove"],
13
+ [/(m)ove$/i, "\\1ove"],
14
+ [/(s)exes$/i, "\\1ex"],
15
+ [/(s)ex$/i, "\\1ex"],
16
+ [/(c)hildren$/i, "\\1hild"],
17
+ [/(c)hild$/i, "\\1hild"],
18
+ [/(m)en$/i, "\\1an"],
19
+ [/(m)an$/i, "\\1an"],
20
+ [/(p)eople$/i, "\\1erson"],
21
+ [/(p)erson$/i, "\\1erson"],
22
+ [/(database)s$/i, "\\1"],
23
+ [/(quiz)zes$/i, "\\1"],
24
+ [/(matr)ices$/i, "\\1ix"],
25
+ [/(vert|ind)ices$/i, "\\1ex"],
26
+ [/^(ox)en/i, "\\1"],
27
+ [/(alias|status)(es)?$/i, "\\1"],
28
+ [/(octop|vir)(us|i)$/i, "\\1us"],
29
+ [/^(a)x[ie]s$/i, "\\1xis"],
30
+ [/(cris|test)(is|es)$/i, "\\1is"],
31
+ [/(shoe)s$/i, "\\1"],
32
+ [/(o)es$/i, "\\1"],
33
+ [/(bus)(es)?$/i, "\\1"],
34
+ [/^(m|l)ice$/i, "\\1ouse"],
35
+ [/(x|ch|ss|sh)es$/i, "\\1"],
36
+ [/(m)ovies$/i, "\\1ovie"],
37
+ [/(s)eries$/i, "\\1eries"],
38
+ [/([^aeiouy]|qu)ies$/i, "\\1y"],
39
+ [/([lr])ves$/i, "\\1f"],
40
+ [/(tive)s$/i, "\\1"],
41
+ [/(hive)s$/i, "\\1"],
42
+ [/([^f])ves$/i, "\\1fe"],
43
+ [/(^analy)(sis|ses)$/i, "\\1sis"],
44
+ [/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)(sis|ses)$/i, "\\1sis"],
45
+ [/([ti])a$/i, "\\1um"],
46
+ [/(n)ews$/i, "\\1ews"],
47
+ [/(ss)$/i, "\\1"],
48
+ [/s$/i, ""]
49
+ ]
50
+ NO_SINGULAR_WORDS = %w(equipment information rice money species series fish sheep jeans police)
51
+ end
52
+ end
53
+
54
+ class String
55
+ include SchemaRD::Utils::Singularizer
56
+ end
@@ -0,0 +1,12 @@
1
+ module SchemaRD
2
+ module Utils
3
+ module StructAssigner
4
+ def assign(hash)
5
+ hash && self.members.each do |key|
6
+ self[key] = hash[key] if hash.has_key?(key)
7
+ self[key] = hash[key.to_sym] if hash.has_key?(key.to_sym)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,56 @@
1
+ require 'webrick'
2
+ require_relative "controller"
3
+
4
+ module SchemaRD
5
+ class WebServer
6
+ attr_reader :config
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+ def setup(srv, options)
11
+ Signal.trap("INT"){ srv.shutdown }
12
+ Signal.trap("TERM"){ srv.shutdown }
13
+
14
+ # アクションメソッド
15
+ srv.mount_proc '/' do |req, res|
16
+ controller = SchemaRD::Controller.new(self.config)
17
+ case req.path
18
+ when "/", "/index"
19
+ controller.index(req, res)
20
+ when /\/tables\/.+/
21
+ controller.show(req, res) if req.request_method == "GET"
22
+ controller.update(req, res) if req.request_method == "POST"
23
+ when /.*\.(js|css|ico)/
24
+ controller.static_file(req, res)
25
+ else
26
+ res.status = Rack::Utils.status_code(404)
27
+ end
28
+ end
29
+ end
30
+
31
+ def start()
32
+ options = {
33
+ :Host => config.webserver_host,
34
+ :Port => config.webserver_port,
35
+ :ServerType => WEBrick::SimpleServer,
36
+ :Logger => WEBrick::Log.new(config.log_output),
37
+ }
38
+ begin
39
+ srv = WEBrick::HTTPServer.new(options);
40
+ setup(srv, options)
41
+ srv.start
42
+ rescue Errno::EADDRINUSE => e
43
+ (options[:Logger] || Logger.new(STDOUT)).error("#{__FILE__}: #{e.to_s}")
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ if $0 == __FILE__
50
+ config = SchemaRD::Configuration.new(ARGV)
51
+ if config.valid?
52
+ SchemaRD::WebServer.new(config).start()
53
+ else
54
+ config.errors.each{|err| puts err }
55
+ end
56
+ end
data/lib/schemard.rb ADDED
@@ -0,0 +1,6 @@
1
+ require_relative 'schemard/web_server'
2
+ require_relative 'schemard/controller'
3
+
4
+ module SchemaRD
5
+ VERSION = "0.2.0"
6
+ end
@@ -0,0 +1,81 @@
1
+ <!DOCTYPE html>
2
+ <html lang="<%= locale.lang %>">
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <link href="normalize.css" rel="stylesheet" media="all">
6
+ <style type="text/css">
7
+ body {
8
+ font-size: small;
9
+ width: 1600px;
10
+ height: 960px;
11
+ }
12
+ div.table {
13
+ position: absolute;
14
+ border: solid 1px #a0a0a0;
15
+ border-radius: 4px;
16
+ display: inline-block;
17
+ z-index: 10;
18
+ user-select: none;
19
+ min-width: 120px;
20
+ padding-bottom: 6px;
21
+ background-color: #ffffff;
22
+ margin: 2px;
23
+ -moz-user-select: none; /* Firefox */
24
+ -webkit-user-select: none; /* Safari、Chrome */
25
+ -ms-user-select: none; /* overIE10 */
26
+ }
27
+ div.default-position {
28
+ position: relative !important;
29
+ }
30
+ .table div { padding: 2px 10px }
31
+ .table div.title {
32
+ background-color: #4078c0;
33
+ color: #ffffff;
34
+ cursor: pointer;
35
+ }
36
+ .editable {
37
+ display: inline-block;
38
+ padding: 4px;
39
+ color: #4078c0;
40
+ position: absolute;
41
+ top: 5px;
42
+ left: 10px;
43
+ z-index: 1000;
44
+ background-color: white;
45
+ }
46
+ .editing { border: solid 3px #b0c4de !important; margin: 0 !important; cursor: -webkit-grab; cursor: -moz-grab; }
47
+ .dragging { cursor: -webkit-grabbing !important; cursor: -moz-grabbing !important; }
48
+ .editing div.title { cursor: -webkit-grab; cursor: -moz-grab; }
49
+ .dragging div.title { cursor: -webkit-grabbing !important; cursor: -moz-grabbing !important; }
50
+ .relation-line, .relation-edge {
51
+ position: absolute;
52
+ z-index: 0;
53
+ }
54
+ .relation-edge-diagonal {
55
+ position: absolute;
56
+ z-index: 0;
57
+ border-bottom: solid 1px black;
58
+ }
59
+ .relation-line .child-1, .relation-line .child-2 { position: absolute; display: inline-block; }
60
+ </style>
61
+ <link rel="shortcut icon" href="favicon.ico">
62
+ <title>ERD</title>
63
+ <script type="text/javascript" src="jquery2.min.js" ></script>
64
+ <script type="text/javascript" src="tableViewer.js" ></script>
65
+ </head>
66
+ <body>
67
+ <label class="editable" ><input type="checkbox" ><%= locale.t("views.edit_checkbox_label") %></label>
68
+ <%- schema.tables.each do |t| -%>
69
+ <div class="table<% if t.default_position? %> default-position<% end %>" data-table-name="<%= t.name %>"
70
+ data-pos-left="<%= t.position["left"]%>" data-pos-top="<%= t.position["top"] %>"
71
+ data-relation-to="<%= t.relations_as_parent.map{|r| r.child_table.name }.join(',') %>"
72
+ data-relation-cardinality="<%=
73
+ t.relations_as_parent.map{|r| r.child_table.name + ":" + r.child_cardinality }.join(',') %>" >
74
+ <div class="title" ><%= t.display_name %></div>
75
+ <% t.columns.each do |c| %>
76
+ <div class="column"><%= c.display_name %></div>
77
+ <%- end -%>
78
+ </div>
79
+ <%- end -%>
80
+ </body>
81
+ </html>
@@ -0,0 +1,156 @@
1
+ <!DOCTYPE html>
2
+ <html lang="<%= locale.lang %>">
3
+ <head>
4
+ <meta charset="utf-8"/>
5
+ <link href="../normalize.css" rel="stylesheet" media="all">
6
+ <style type="text/css">
7
+ body { font-size: small; }
8
+ header {
9
+ padding: 10px 0;
10
+ border-bottom: solid 2px #87cefa;
11
+ background-color: #004680;
12
+ color: #ffffff;
13
+ }
14
+ header a { color: #ffffff; cursor: pointer; }
15
+ header .title {
16
+ width: 90%;
17
+ margin: 0 auto;
18
+ font-size: large;
19
+ }
20
+ header .title #img {
21
+ background-image: url(../favicon.ico);
22
+ background-size: contain;
23
+ display: inline-block;
24
+ width: 30px;
25
+ }
26
+ header .title span { padding: 5px; }
27
+ section { width: 90%; margin: 0 auto; }
28
+ section > h3 {
29
+ color: #004680;
30
+ font-weight: normal;
31
+ border-bottom: solid 2px #d3d3d3;
32
+ margin: 12px 0;
33
+ font-size: 1.5em;
34
+ }
35
+ th { font-weight: normal; }
36
+ table.no-grid th {
37
+ text-align: right;
38
+ vertical-align: top;
39
+ color: #004680;
40
+ }
41
+ table.no-grid td { padding: 2px 15px; }
42
+ pre { font-family: sans-serif; font-size: medium; }
43
+ table.grid { width: 100%; }
44
+ table.grid th, table.grid td { padding: 2px 10px; border: solid 1px #d3d3d3; }
45
+ table.grid th {
46
+ text-align: left;
47
+ color: #ffffff;
48
+ background-color: #004680;
49
+ }
50
+ div.wrap { margin-bottom: 30px; }
51
+ </style>
52
+ <link rel="shortcut icon" href="../favicon.ico">
53
+ <%-
54
+ table = schema.table(table_name)
55
+ -%>
56
+ <title>ERD [<%= table.display_name %>]</title>
57
+ <script type="text/javascript" src="../jquery2.min.js" ></script>
58
+ <script type="text/javascript" src="../tableViewer.js" ></script>
59
+ </head>
60
+ <body>
61
+ <body>
62
+ <div class="wrap">
63
+ <header>
64
+ <div class="title">
65
+ <span><a data-link-url="/" ><i id="img" >&nbsp;</i>ERD</a></span>
66
+ <span>▶</span>
67
+ <span><%= table.display_name %><% if table_name != table.display_name %>(<%= table_name %>)<% end %></span>
68
+ </div>
69
+ </header>
70
+
71
+ <section>
72
+ <h3><%= locale.t("views.table_summary_title") %></h3>
73
+ <table class="no-grid">
74
+ <tbody>
75
+ <tr>
76
+ <th> <%= locale.t("views.table_name") %> </th><td> <%= table.display_name %> </td>
77
+ </tr>
78
+ <%- if locale.lang != "en" %>
79
+ <tr>
80
+ <th> <%= locale.t("views.table_name_en") %> </th><td> <%= table.name %> </td>
81
+ </tr>
82
+ <%- end -%>
83
+ <tr>
84
+ <th> <%= locale.t("views.parent_tables") %> </th>
85
+ <td> <%= table.relations_as_child.map(&:parent_table).map do |t|
86
+ "<a data-link-url='#{t.name}' >#{t.display_name}</a>"
87
+ end.join(", ") -%> </td>
88
+ </tr>
89
+ <tr>
90
+ <th> <%= locale.t("views.child_tables") %> </th>
91
+ <td> <%= table.relations_as_parent.map(&:child_table).map do |t|
92
+ "<a data-link-url='#{t.name}' >#{t.display_name}</a>"
93
+ end.join(", ") -%> </td>
94
+ </tr>
95
+ </tbody>
96
+ </table>
97
+ </section>
98
+
99
+ <section>
100
+ <h3><%= locale.t("views.description") %></h3>
101
+ <pre><%= table.description %></pre>
102
+ </section>
103
+
104
+ <section>
105
+ <h3><%= locale.t("views.column_definition") %></h3>
106
+ <table class="grid">
107
+ <tbody>
108
+ <tr>
109
+ <th> <%= locale.t("views.column_name") %> </th>
110
+ <%- if locale.lang != "en" %>
111
+ <th> <%= locale.t("views.column_name_en") %> </th>
112
+ <%- end -%>
113
+ <th> <%= locale.t("views.column_type") %> </th>
114
+ <th> <%= locale.t("views.column_precision") %> </th>
115
+ <th> NULL </th>
116
+ <th> <%= locale.t("views.column_default") %> </th>
117
+ <th> <%= locale.t("views.description") %> </th>
118
+ </tr>
119
+ <%- table.columns.each do |col| -%>
120
+ <tr>
121
+ <td> <%= col.display_name %> </td>
122
+ <%- if locale.lang != "en" %>
123
+ <td> <%= col.name %></td>
124
+ <%- end -%>
125
+ <td> <%= col.type %></td>
126
+ <td> <%= col.type == "decimal" ? "#{col.precision},#{col.scale}" : col.limit %> </td>
127
+ <td> <%= col.null || "false" %> </td>
128
+ <td> <%= col.default || "NULL" %> </td>
129
+ <td> <%= col.description %> </td>
130
+ </tr>
131
+ <%- end -%>
132
+ </tbody>
133
+ </table>
134
+ </section>
135
+
136
+ <section>
137
+ <h3><%= locale.t("views.index_definition") %></h3>
138
+ <table class="grid">
139
+ <tbody>
140
+ <tr>
141
+ <th> <%= locale.t("views.index_unique") %> </th>
142
+ <th> <%= locale.t("views.index_target_columns") %> </th>
143
+ <th> <%= locale.t("views.index_name") %> </th>
144
+ </tr>
145
+ <%- table.indexes.each do |idx| -%>
146
+ <tr>
147
+ <td> <%= idx.unique %> </td>
148
+ <td> <%= idx.columns.map {|c| col = table.columns.find{|col| col.name == c }; col && col.display_name }.join(", ") %> </td>
149
+ <td> <%= idx.name %> </td>
150
+ </tr>
151
+ <%- end -%>
152
+ </section>
153
+
154
+ </div><!-- wrap -->
155
+ </body>
156
+ </html>
data/schemard.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "schemard"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "schemard"
8
+ spec.version = SchemaRD::VERSION
9
+ spec.authors = ["ken TANAKA"]
10
+ spec.email = ["x.tanaka.ken.at.gmail.com"]
11
+
12
+ spec.summary = "SchemaRD is a ERD Viewer for schema.rb."
13
+ spec.description = <<-eof
14
+ SchemaRD is a Entity Relationship Diagram Viewer for schema.rb which is used on Ruby On Rails.
15
+ You can browse Entity Relationship Diagram of your schema.rb, on your WebBrowser.
16
+ eof
17
+ spec.homepage = "https://github.com/xketanaka/schemard"
18
+ spec.license = "MIT"
19
+
20
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
21
+ f.match(%r{^(test|spec|features)/})
22
+ end
23
+ spec.executables = ["schemard"]
24
+ spec.require_paths = ["lib"]
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.0"
27
+ spec.add_development_dependency "rake", "~> 0.9"
28
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: schemard
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - ken TANAKA
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
41
+ description: |2
42
+ SchemaRD is a Entity Relationship Diagram Viewer for schema.rb which is used on Ruby On Rails.
43
+ You can browse Entity Relationship Diagram of your schema.rb, on your WebBrowser.
44
+ email:
45
+ - x.tanaka.ken.at.gmail.com
46
+ executables:
47
+ - schemard
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - ".gitignore"
52
+ - Gemfile
53
+ - LICENSE.txt
54
+ - README.ja.md
55
+ - README.md
56
+ - Rakefile
57
+ - bin/schemard
58
+ - lib/contents/favicon.ico
59
+ - lib/contents/jquery2.min.js
60
+ - lib/contents/normalize.css
61
+ - lib/contents/tableViewer.js
62
+ - lib/locales/messages.yml
63
+ - lib/schemard.rb
64
+ - lib/schemard/controller.rb
65
+ - lib/schemard/metadata.rb
66
+ - lib/schemard/rdoc_parser.rb
67
+ - lib/schemard/relation_generator.rb
68
+ - lib/schemard/schema.rb
69
+ - lib/schemard/schema_parser.rb
70
+ - lib/schemard/utils/localizer.rb
71
+ - lib/schemard/utils/singularizer.rb
72
+ - lib/schemard/utils/struct_assigner.rb
73
+ - lib/schemard/web_server.rb
74
+ - lib/templates/index.html.erb
75
+ - lib/templates/show.html.erb
76
+ - schemard.gemspec
77
+ homepage: https://github.com/xketanaka/schemard
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.6.11
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: SchemaRD is a ERD Viewer for schema.rb.
101
+ test_files: []