A simple database schema generator

这个是什么

标题翻译过来就是一个简单的数据库Schema生成器,源代码在Github上面传送门
你需要安装好Ruby,Graphviz,然后把代码clone下来就可以运行了。

这个的原理

Graphviz是一个根据特定语言的可视化软件,它可以根据dot文件里面描述的内容生成一张图片。
假设我有下面一段数据库的Schema

Club
==================================================
id                                         int(11)
name                                  varchar(255)
address                               varchar(255)
expired_at                                datetime
created_at                                datetime
updated_at                                datetime
ecard                                      int(11)
image_keys                            varchar(255)
portable                                tinyint(1)
--------------------------------------------------

School
==================================================
id                                         int(11)
name                                  varchar(255)
address                               varchar(255)
ecard                                      int(11)
expired_at                                datetime
created_at                                datetime
updated_at                                datetime
portable                                tinyint(1)
--------------------------------------------------

Game
==================================================
id                                         int(11)
start_at                                  datetime
end_at                                    datetime
lat                                         double
lng                                         double
address                               varchar(255)
created_at                                datetime
updated_at                                datetime
name                                  varchar(255)
image_key                             varchar(255)
image_keys                            varchar(255)
--------------------------------------------------

ClubGame
==================================================
game_id                                    int(11)
club_id                                    int(11)
--------------------------------------------------

SchoolGame
==================================================
game_id                                    int(11)
school_id                                  int(11)
--------------------------------------------------

ClubProfile
==================================================
id                                         int(11)
user_id                                    int(11)
club_id                                    int(11)
avatar_key                            varchar(255)
course_id                                  int(11)
gender                                     int(11)
birthday                                  datetime
point                                      int(11)
ce                                         int(11)
created_at                                datetime
updated_at                                datetime
realname                              varchar(255)
--------------------------------------------------

SchoolProfile
==================================================
id                                         int(11)
user_id                                    int(11)
avatar_key                            varchar(255)
classroom_id                               int(11)
gender                                     int(11)
birthday                                  datetime
point                                      int(11)
ce                                         int(11)
created_at                                datetime
updated_at                                datetime
realname                              varchar(255)
school_id                                  int(11)
--------------------------------------------------

好吧,其实上面的schema也是我生成出来的,因为之前Rails里面是有schema.rb的,所以我觉得我的Cubanana里面也要有一个schema.txt

所以当你有这样一个schema.txt的时候,你可以看到单独的表中所包含的字段,但是你也想看到表与表之间的联系,这个时候,其实最简单的就是foreign_key,Rails里面的convention over configuration思想其实让你在设计数据表的时候就考虑数据表之间的关联,虽然它没有真正的foreign_key这个东西,但你知道当另一个表(User)里面出现club_id的时候,你就知道这两个其实是有关联的。

所以你需要的是把schema.txt解析生成为schema.dot文件,一个简单的dot文件例如:

digraph G {
  rankdir=LR
  node [shape=box, color=blue]
  node1 [style=filled] 
  node2 [style=filled, fillcolor=red] 
  node0 -> node1 -> node2
}

对应了下图

G

简单来说一个图,包含了node(节点),edge(边),我这边为了偷懒,就用了无向图,也就是没有箭头的。

上面Schema中每一个Model其实就是一个节点,那么对应了下面的dot语言

ClubGame [label="ClubGame|{game_id|club_id|club_game_id}"];

边的描述更加简单

Game -> SchoolGame [dir="none"]

详细的你可以看Graphviz的文档,RTFD,:)

了解了原理,那么接下来就是解析文件,一通操作:

def split_into_nodes
    original = File.open(@source, 'r') { |file| file.readlines }
    blankless = original.reject{ |line| line.match(/^$/) }

    @nodes = blankless
      .join()
      .split("--------------------------------------------------").map do |b|
      sources = b.lines.reject{|line| line == "\n"}
      name = sources.first.gsub("\n",'')
      attrs = sources[2..-1].map { |e| e.split(' ')
      .join(':') }
      .reject{ |s| s.include? "created_at" }
      .reject{ |s| s.include? "updated_at"}
      .reject{ |s| s == "id:int(11)"}
      .concat ["#{name.underscore}_id:int(11)"]
      .uniq
      sn = SchemaNode.new(name, attrs)
    end
end

这么做是为了让你把上面Schema分解成单独的SchemaNode,那么现在节点有了,用to_structs方法就可以生成节点了,那么边呢?
所以其实就是,两点生成一条直线,唯一要做的就是你需要判断它们俩能不能连在一起,而连不连在一起就是说我一个表里面有没有另一个表的id,如下:

class Link
  def initialize(node_a, node_b)
    @node_a = node_a
    @node_b = node_b
  end

  def link?
    case_a = @node_b.attrs.include?("#{@node_a.name.underscore}_id:int(11)")
    case_b = @node_a.attrs.include?("#{@node_b.name.underscore}_id:int(11)")
    case_a || case_b
  end
end

哈哈哈,一开始遇到了一个问题,让我生成的图少了好几条线,百思不得其解,后来发现是因为比如ClubGame小写之后拼接的id是clubgame_id,而其实应该是club_game_id,Camel case 的锅,所以会有一个monkey patch:

class String
  def underscore
    self.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
  end
end

这个代替了downcase。

好的,非常棒,那么两个节点的操作完了,你生成的那么多节点呢???

那不就是两两组合吗,然后把连接着一起的数出来吗?鄙视写for循环的程序员,而且还是两层的。在数学上,这个是排列组合的问题,你们的数学都还给老师了吗???
所以Ruby的Array有一个方法叫做 combination 啊!其他语言也有,(尽管可能它也是for循环),重要的是,你写代码的时候,要知道它的数学原理。能简化你很多不必要的低级操作,避免你成为一个低级的程序员。

这个的演示

Example

最终的结果如图,我偷懒,不画箭头,但是箭头无非就是改变一下edge的判断条件。

May the source be with U, gays!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,443评论 0 13
  • 转载,觉得这篇写 SQLAlchemy Core,写得非常不错。不过后续他没写SQLAlchemy ORM... ...
    非梦nj阅读 5,371评论 1 14
  • 程序设计中常使用树型结构来表征某些数据的关联关系,如上下级、栏目结构、商品分类、菜单、回复等。 分类的层级关系可以...
    JunChow520阅读 4,084评论 4 3
  • 1.在苹果的应用商店下载Cisco 下载成功之后在手机桌面打开软件 打开软件点击链接,添加 填写说明和服务器地址,...
    62AbC49g阅读 10,385评论 0 0
  • 开篇第一句。 如果你是抱着完成写作梦想而阅读本文的鱼儿,那么遗憾的告诉你,这里,是一片靠文字吃饭的海洋。 本文所讲...
    星冠伯爵阅读 968评论 0 16