dbtodoc 0.1.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f435503e31f05aaa1598c8d7fee82519cc38ecc36b5ce0e4d3f783948579543
4
- data.tar.gz: 10177a6e91718a7c8e4da15bc5db59e0351f6e6ba35719e272e431a0e8e119fd
3
+ metadata.gz: 3d5d597bf0680eaf4dd5881ab460fed46e2345c17712ab12d65f52d91a2ece76
4
+ data.tar.gz: 7d307ebac51b97dc361086fec7c542a68b347e8e447db1a1450a5c5afcb6a8ef
5
5
  SHA512:
6
- metadata.gz: c7408cbe931b98cc51d0850fce98a8150094f141a04838afb5f2f877c59e033d11ad2a39cc65d8c61f157bd38a8837b06ae4e976d71acedd47b99db9c749eea1
7
- data.tar.gz: 804cf971c9051fcdb8602f87001140659ea04524af9aea2e039315cc8cc48a1ebdd92f3fa5ea444b07543b025c42fe60d13d215bf3b1ed53098791a2f610bced
6
+ metadata.gz: e61948c7303f93dd8740dccf6b0aac577f3901d1834ccfccea6dab8975bfe7c1f911582aadac9424be8d5325a69b1a74408e8a292ed648015eb5bd51a78b8ae8
7
+ data.tar.gz: b533c3c6f273f89b0098f9a9488bf91fc15a7eb8fc140d11ac0745c1084d07a845cfdb170c17241e306a85a6e5532282ac0858b534f2ff3cdfa240cfbb2540e7
data/README.md CHANGED
@@ -1,31 +1,199 @@
1
- # Dbtodoc
1
+ # DBToDoc
2
2
 
3
- TODO: Delete this and the text below, and describe your gem
3
+ DBToDoc 是一个专门用于将 Rails 项目的数据库 schema 导出为文档的Ruby gem。它支持多种输出格式,包括 schema.rb、CSV Excel,帮助开发者快速生成数据库文档。
4
4
 
5
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/dbtodoc`. To experiment with that code, run `bin/console` for an interactive prompt.
5
+ ## 功能特性
6
6
 
7
- ## Installation
7
+ - 🚀 **多格式支持**:导出为 schema.rb、CSV 或 Excel 格式,默认 Excel
8
+ - 🗄️ **多数据库兼容**:支持 MySQL、PostgreSQL、SQLite
9
+ - 🌐 **国际化支持**:自动读取 Rails 的 locales 文件进行字段翻译
10
+ - 🎨 **美观输出**:Excel 格式支持样式设置和颜色主题
11
+ - 🔍 **智能分析**:自动解析数据库配置和表结构
12
+ - 📊 **详细文档**:包含字段名、类型、约束、默认值等完整信息
8
13
 
9
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
14
+ ## 📋 系统要求
10
15
 
11
- Install the gem and add to the application's Gemfile by executing:
16
+ - Ruby >= 2.6.0
17
+ - Rails 项目(包含 config/database.yml)
18
+ - 支持的数据库:MySQL、PostgreSQL、SQLite
12
19
 
13
- $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
20
+ ## 🚀 安装
14
21
 
15
- If bundler is not being used to manage dependencies, install the gem by executing:
22
+ ### Rubygems 安装
16
23
 
17
- $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
24
+ ```bash
25
+ gem install dbtodoc
26
+ ```
18
27
 
19
- ## Usage
28
+ ### 从源码安装
20
29
 
21
- TODO: Write usage instructions here
30
+ ```bash
31
+ git clone https://github.com/shuhjx/dbtodoc.git
32
+ cd dbtodoc
33
+ gem build dbtodoc.gemspec
34
+ gem install dbtodoc-*.gem
35
+ ```
22
36
 
23
- ## Development
37
+ ## 📖 使用方法
24
38
 
25
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
39
+ ### 基本用法
26
40
 
27
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
41
+ DBToDoc 提供了一个简单的命令行接口:
28
42
 
29
- ## Contributing
43
+ ```bash
44
+ # 导出为 schema.rb 格式
45
+ dbtodoc --format=ruby
30
46
 
31
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/dbtodoc.
47
+ # 导出为 schema.sql 格式
48
+ dbtodoc --format=sql
49
+
50
+ # 导出为 CSV 格式
51
+ dbtodoc --format=csv
52
+
53
+ # 导出为 Excel 格式
54
+ dbtodoc --format=excel
55
+
56
+ # 指定项目路径
57
+ dbtodoc --path=/path/to/rails/project --format=excel
58
+ ```
59
+
60
+ ### 在 Ruby 代码中使用
61
+
62
+ ```ruby
63
+ require 'dbtodoc'
64
+
65
+ # 导出为 schema.rb 格式
66
+ Dbtodoc.start(format: 'ruby')
67
+
68
+ # 导出为 schema.sql 格式
69
+ Dbtodoc.start(format: 'sql')
70
+
71
+ # 导出为 CSV 格式
72
+ Dbtodoc.start(format: 'csv')
73
+
74
+ # 导出为 Excel 格式
75
+ Dbtodoc.start(format: 'excel')
76
+
77
+ # 指定项目路径
78
+ Dbtodoc.start(path: '/path/to/rails/project', format: 'excel')
79
+ ```
80
+
81
+ ## 📊 输出格式说明
82
+
83
+ ### CSV 格式
84
+ CSV 文件包含以下列:
85
+ - 表名
86
+ - 字段名
87
+ - 类型
88
+ - NULL许可
89
+ - 默认值
90
+ - 日本語名(通过 i18n 获取)
91
+ - 说明
92
+ - 样本数据
93
+ - 索引名
94
+
95
+ ### Excel 格式
96
+ Excel 文件具有以下特性:
97
+ - 📋 每张表单独分组显示
98
+ - 🎨 专业的颜色主题:
99
+ - 蓝色:表名行
100
+ - 绿色:表头
101
+ - 白色:数据行
102
+ - 浅绿色:主键字段
103
+ - 📏 自动调整列宽
104
+ - 🔤 支持日文字体(MS Pゴシック)
105
+ - 📐 完整的边框样式
106
+
107
+ Excel 输出包含以下列:
108
+ - フィールド名(字段名)
109
+ - 型(类型)
110
+ - NULL許可(NULL许可)
111
+ - デフォルト値(默认值)
112
+ - 日本語名(日文字段名)
113
+ - 説明(说明)
114
+ - サンプルデータ(样本数据)
115
+ - 索引名(索引名)
116
+
117
+ ## 🌍 国际化支持
118
+
119
+ DBToDoc 自动读取 Rails 项目的 `config/locales/*.yml` 文件,支持以下国际化特性:
120
+
121
+ - 📝 **表名翻译**:自动将英文表名转换为本地语言
122
+ - 🏷️ **字段名翻译**:为字段名提供多语言支持
123
+ - 🔄 **智能复数处理**:自动处理单复数形式转换
124
+
125
+ 示例 locales 配置:
126
+
127
+ ```yaml
128
+ # config/locales/ja.yml
129
+ ja:
130
+ activerecord:
131
+ models:
132
+ user: ユーザー
133
+ post: 投稿
134
+ attributes:
135
+ user:
136
+ name: 名前
137
+ email: メール
138
+ ```
139
+
140
+ ## 🔧 技术架构
141
+
142
+ ### 核心组件
143
+
144
+ 1. **Dbtodoc::Schema** - 重写 ActiveRecord::Schema 方法,拦截表定义过程
145
+ 2. **Dbtodoc::Definition** - 处理表和字段定义的收集
146
+ 3. **Dbtodoc::I18n** - 提供国际化支持
147
+ 4. **Dbtodoc::Doc::Csv** - CSV 格式导出
148
+ 5. **Dbtodoc::Doc::Excel** - Excel 格式导出
149
+
150
+ ### 工作流程
151
+
152
+ ```
153
+ 读取 database.yml → 连接数据库 → 生成 schema.rb → 转换为目标格式
154
+ ```
155
+
156
+ ## 📁 文件输出位置
157
+
158
+ 所有输出文件都保存在 Rails 项目的 `tmp/` 目录下:
159
+
160
+ ```
161
+ tmp/
162
+ ├── {database_name}_schema.rb # schema 格式
163
+ ├── {database_name}.csv # CSV 格式
164
+ └── {database_name}.xlsx # Excel 格式
165
+ ```
166
+
167
+ ## 🛠️ 开发环境设置
168
+
169
+ ### 克隆项目
170
+
171
+ ```bash
172
+ git clone https://github.com/shuhjx/dbtodoc.git
173
+ cd dbtodoc
174
+ ```
175
+
176
+ ### 安装依赖
177
+
178
+ ```bash
179
+ bundle install
180
+ ```
181
+
182
+ ### 运行测试(待完成)
183
+
184
+ ```bash
185
+ rake spec
186
+ ```
187
+
188
+ ### 构建 gem
189
+
190
+ ```bash
191
+ rake build
192
+ ```
193
+
194
+ ## 🙏 致谢
195
+
196
+ 感谢以下开源项目:
197
+ - [RubyXL](https://rubyxl.github.io/) - Excel 文件处理
198
+ - [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) - 数据库抽象层
199
+ - [CLI::UI](https://github.com/shopify/cli-ui) - 用户界面组件
data/bin/dbtodoc CHANGED
@@ -6,16 +6,16 @@ require 'optparse'
6
6
  class ArgsParser
7
7
  def self.parse!(args)
8
8
  options = {
9
- type: 'excel'
9
+ format: 'excel'
10
10
  }
11
11
  opt_parser = OptionParser.new do |opts|
12
12
  opts.banner = "Usage: dbtodoc [options]"
13
13
 
14
- opts.on('-t', '--type TYPE', "指定输出类型,默认值:excel,可选值:schema, csv, excel") do |o|
15
- options[:type] = o
14
+ opts.on('-f', '--format FORMAT', "指定输出格式,默认值:excel,可选值:ruby, sql, csv, excel") do |o|
15
+ options[:format] = o
16
16
  end
17
17
 
18
- opts.on('-h', '--help', "显示帮助\n例:dbtodoc -t csv /rails/root/path") do
18
+ opts.on('-h', '--help', "显示帮助\n例:dbtodoc -f csv /rails/root/path") do
19
19
  puts opts
20
20
  exit
21
21
  end
@@ -35,8 +35,8 @@ unless File.exist?(path)
35
35
  puts "#{path}: 文件或目录不存在"
36
36
  exit 1
37
37
  end
38
- options[:path] = path
38
+ options[:path] = File.expand_path(path, Dir.pwd)
39
+ Dir.chdir(options[:path]) if path != '.' # 切换到目标目录
39
40
 
40
41
  require 'dbtodoc'
41
-
42
- Dbtodoc.start(options)
42
+ Dbtodoc.start(options)
@@ -17,7 +17,7 @@ module Dbtodoc
17
17
  before_define()
18
18
  instance_eval(&block)
19
19
  ensure
20
- after_define()
20
+ after_define() rescue nil
21
21
  end
22
22
 
23
23
  def index(column_names, **options)
@@ -33,7 +33,13 @@ module Dbtodoc
33
33
  end
34
34
 
35
35
  def database
36
- @_database ||= ActiveRecord::Base.connection.current_database
36
+ return @_database if @_database
37
+ if ActiveRecord::Base.connection.respond_to?(:current_database)
38
+ @_database = ActiveRecord::Base.connection.current_database
39
+ else
40
+ # sqlite3 数据库文件路径
41
+ @_database = File.basename(ActiveRecord::Base.connection_db_config.database)
42
+ end
37
43
  end
38
44
  private
39
45
  # 写入文档
@@ -91,25 +97,48 @@ module Dbtodoc
91
97
  def add_foreign_key(from_table, to_table, **options)
92
98
  #TODO 外键
93
99
  end
100
+ def enable_extension(extension_name)
101
+ # TODO
102
+ end
103
+
104
+ # def test(name)
105
+ # if !@definition
106
+ # version = ActiveRecord::Migration.current_version
107
+ # klass = Class.new(ActiveRecord::Migration::Compatibility.find(version)) do
108
+ # include ActiveRecord::Schema::Definition
109
+ # end
110
+ # @definition = klass.new
111
+ # end
112
+ # @definition.instance_eval do
113
+ # create_table("test_bak") do |t|
114
+ # puts "#{name}: #{t.method(name).source_location}"
115
+ # end
116
+ # drop_table("test_bak")
117
+ # end
118
+ # end
94
119
 
95
120
  def method_missing(name, *args, &block)
96
121
  type = case name
97
- when :bigint
122
+ when :bigint, :bigserial
98
123
  ActiveRecord::Type.registry.lookup(:big_integer)
124
+ when :serial
125
+ ActiveRecord::Type.registry.lookup(:integer)
99
126
  else
100
127
  ActiveRecord::Type.registry.lookup(name.to_sym) rescue nil
101
128
  end
129
+ column = args[0]
130
+ options = args[1] || {}
102
131
  if type
103
- column = args[0]
104
- options = args[1] || {}
105
132
  # 调用type_to_sql方法
106
133
  sql_type = ActiveRecord::Base.connection.schema_creation.send(:type_to_sql, type.type, **options)
107
134
  add_row(column, sql_type, **options)
135
+ elsif native_type = ActiveRecord::Base.adapter_class.native_database_types[name]
136
+ add_row(column, native_type[:name], **options)
108
137
  else
109
138
  puts '------------'
110
139
  puts "name: #{name}, args: #{args}"
111
140
  puts '------------'
112
- super
141
+ raise "Unknown method: #{name}"
113
142
  end
114
143
  end
115
144
  end
@@ -2,7 +2,7 @@ require 'csv'
2
2
  module Dbtodoc
3
3
  module Doc
4
4
  module Csv
5
- DOC_HEADER = %w(表名 字段名 类型 NULL許可 默认値 日本語名 説明 样本数据 索引名)
5
+ DOC_HEADER = %w(テーブル名 フィールド名 NULL許可 デフォルト値 日本語名 説明 サンプルデータ 索引名)
6
6
 
7
7
  private
8
8
  def before_define
@@ -45,7 +45,6 @@ module Dbtodoc
45
45
 
46
46
  def add_table_name_row(table_name)
47
47
  [table_name, i18n.table_name(table_name), *Array.new(DOC_HEADER.size - 2, nil)].each_with_index do |value, col|
48
- @col_max_widths[col+1] = [@col_max_widths[col+1], value.to_s.length].max if value
49
48
  cell = @worksheet.add_cell(@max_row, col + 1, value)
50
49
  # 设置背景颜色(蓝色)
51
50
  set_cell_style(cell, :table_name)
@@ -0,0 +1,15 @@
1
+ module Dbtodoc
2
+ module Doc
3
+ module Ruby
4
+ def self.dump(filename)
5
+ File.open(filename, 'w:utf-8') do |file|
6
+ if ActiveRecord.version >= '7.1'
7
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection_pool, file)
8
+ else
9
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,29 @@
1
+ module Dbtodoc
2
+ module Doc
3
+ module Sql
4
+ def self.dump(filename)
5
+ pool = ActiveRecord::Base.connection_pool
6
+ db_config = pool.db_config
7
+ klass = case db_config.adapter
8
+ when /mysql|trilogy/
9
+ 'ActiveRecord::Tasks::MySQLDatabaseTasks'
10
+ when /postgresql/
11
+ 'ActiveRecord::Tasks::PostgreSQLDatabaseTasks'
12
+ when /sqlite/
13
+ 'ActiveRecord::Tasks::SQLiteDatabaseTasks'
14
+ else
15
+ raise "Unknown adapter: #{db_config.adapter}"
16
+ end
17
+ klass = klass.constantize
18
+ converted = klass.respond_to?(:using_database_configurations?) && klass.using_database_configurations?
19
+ # db_config = ActiveRecord::Base.configurations.resolve(db_config)
20
+ config = converted ? db_config : db_config.configuration_hash
21
+ task = db_config.adapter =~ /sqlite/ ? klass.new(config, '.') : klass.new(config)
22
+
23
+ flags = nil
24
+ # flags = ["--exclude-table-data '*'", '--no-comments', '--no-publications', '--no-subscriptions', '--no-security-labels', '--no-tablespaces', '--no-unlogged-table-data'] if db_config.adapter =~ /postgresql/
25
+ task.structure_dump(filename, flags)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -36,14 +36,14 @@ module ActiveRecord
36
36
  @class_for_version ||= {}
37
37
  @class_for_version[version] ||= Class.new do
38
38
  include ::Dbtodoc::Definition
39
- if @@doc_type_module
40
- include @@doc_type_module
39
+ if @@doc_format_module
40
+ include @@doc_format_module
41
41
  end
42
42
  end
43
43
  end
44
44
 
45
- def set_doc_type(type)
46
- @@doc_type_module = case type
45
+ def set_doc_format(format)
46
+ @@doc_format_module = case format
47
47
  when 'csv'
48
48
  require_relative('./doc/csv.rb')
49
49
  ::Dbtodoc::Doc::Csv
@@ -51,7 +51,7 @@ module ActiveRecord
51
51
  require_relative './doc/excel.rb'
52
52
  ::Dbtodoc::Doc::Excel
53
53
  else
54
- raise ArgumentError, "Invalid doc type: #{type}"
54
+ raise ArgumentError, "Invalid doc format: #{format}"
55
55
  end
56
56
  end
57
57
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dbtodoc
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/dbtodoc.rb CHANGED
@@ -24,7 +24,6 @@ module Dbtodoc
24
24
 
25
25
  def self.start(options)
26
26
  path = options[:path] || '.'
27
- Dir.chdir(path) if path != '.' # 切换到目标目录
28
27
 
29
28
  db_config_file = File.join(path, 'config/database.yml')
30
29
  unless File.exist?(db_config_file)
@@ -55,10 +54,13 @@ module Dbtodoc
55
54
  case adapter
56
55
  when 'mysql2'
57
56
  require 'mysql2'
58
- when 'pg'
57
+ when 'postgresql'
59
58
  require 'pg'
60
59
  when 'sqlite3'
61
60
  require 'sqlite3'
61
+ _tmp = all_db_configs[db_name].update('database' => File.join(path, db_name))
62
+ db_name = File.basename(db_name)
63
+ all_db_configs[db_name] = _tmp
62
64
  else
63
65
  puts "Unknown adapter: #{adapter}"
64
66
  exit 1
@@ -69,29 +71,31 @@ module Dbtodoc
69
71
 
70
72
  # 确保tmp目录存在
71
73
  FileUtils.mkdir_p File.join(path, 'tmp')
72
-
73
- # 生成数据库 schema 文件
74
- schema_file = File.join(path, "tmp/#{db_name}_schema.rb")
75
- File.open(schema_file, 'w:utf-8') do |file|
76
- if ActiveRecord.version >= '7.1'
77
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection_pool, file)
78
- else
79
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
74
+
75
+ format = options[:format].downcase
76
+ case format
77
+ when 'sql'
78
+ filename = File.join(path, "tmp/#{db_name}.sql")
79
+ require_relative File.join(__dir__, 'dbtodoc/doc/sql.rb')
80
+ Dbtodoc::Doc::Sql.dump(filename)
81
+ puts "SQL file: #{filename}"
82
+ when 'ruby', 'csv', 'excel'
83
+ schema_file = File.join(path, "tmp/#{db_name}.rb")
84
+ require_relative File.join(__dir__, 'dbtodoc/doc/ruby.rb')
85
+ # 生成数据库 schema 文件
86
+ Dbtodoc::Doc::Ruby.dump(schema_file)
87
+ if format == 'ruby'
88
+ puts "Ruby file: #{schema_file}"
89
+ exit
80
90
  end
81
- end
82
-
83
- case options[:type].downcase
84
- when 'schema'
85
- puts "Schema file: #{schema_file}"
86
- when 'csv', 'excel'
87
91
  require_relative File.join(__dir__, 'dbtodoc/schema.rb')
88
- ActiveRecord::Schema.set_doc_type(options[:type])
92
+ ActiveRecord::Schema.set_doc_format(options[:format])
89
93
  #执行schema.rb文件,生成csv|excel文件
90
- eval File.read(schema_file), binding
91
- puts "CSV file: #{File.join(path, "tmp/#{db_name}.csv")}" if options[:type] == 'csv'
92
- puts "Excel file: #{File.join(path, "tmp/#{db_name}.xlsx")}" if options[:type] == 'excel'
94
+ eval File.read(schema_file)
95
+ puts "CSV file: #{File.join(path, "tmp/#{db_name}.csv")}" if options[:format] == 'csv'
96
+ puts "Excel file: #{File.join(path, "tmp/#{db_name}.xlsx")}" if options[:format] == 'excel'
93
97
  else
94
- puts "Unknown type: #{options[:type]}"
98
+ puts "Unknown format: #{options[:format]}"
95
99
  end
96
100
  end
97
101
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dbtodoc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - shuhjx
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-01-05 00:00:00.000000000 Z
11
+ date: 2026-01-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: 将 Rails 项目的数据库 schema 导出为文档,支持 schema, csv, excel 格式
14
14
  email:
@@ -18,17 +18,17 @@ executables:
18
18
  extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
- - ".DS_Store"
22
21
  - ".rspec"
23
22
  - README.md
24
23
  - Rakefile
25
- - bin/.DS_Store
26
24
  - bin/dbtodoc
27
25
  - dbtodoc.gemspec
28
26
  - lib/dbtodoc.rb
29
27
  - lib/dbtodoc/definition.rb
30
28
  - lib/dbtodoc/doc/csv.rb
31
29
  - lib/dbtodoc/doc/excel.rb
30
+ - lib/dbtodoc/doc/ruby.rb
31
+ - lib/dbtodoc/doc/sql.rb
32
32
  - lib/dbtodoc/i18n.rb
33
33
  - lib/dbtodoc/schema.rb
34
34
  - lib/dbtodoc/version.rb
data/.DS_Store DELETED
Binary file
data/bin/.DS_Store DELETED
Binary file