exwiw 0.2.5 → 0.2.6
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 +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +17 -1
- data/lib/exwiw/schema_generator.rb +65 -45
- data/lib/exwiw/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2ff943aae77c0ed0f79dc80c2e68527badcae7c6b330e89aec6a019adf0dd1e5
|
|
4
|
+
data.tar.gz: 8a146a76aea7ab0bd3aeabb27ccf789f575f86e1d965b64b2432c250addb003b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6dbd0212c4ca02aba3839f17bfe7fc45283f17cb7264d903527fbafda04a4cc9b5c756762a1422fae549b143a60ec825669581311ada63972c2288bdb744e47c
|
|
7
|
+
data.tar.gz: 6364942e8ee51055eb2ed2bffc16995b1a19c64b977790fa8ff4222742f034ae6d4b0b7410f779f70655bb2d6d3ea33af7321853727a2c9300adcdcbd45fc763
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.2.6] - 2026-05-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `schema:generate` now supports Rails multiple-database setups (`connects_to`). Models are bucketed by their database (`connection_db_config.name`, e.g. `primary` / `analytics`) and each database's config files are written into its own subdirectory under `OUTPUT_DIR_PATH` (`exwiw/primary/`, `exwiw/analytics/`, ...). Rails-managed tables (`schema_migrations` / `ar_internal_metadata`) are emitted under whichever database actually owns them. Single-database apps are unaffected and still write flat into the output directory. This replaces the previous behavior of raising `MultipleDatabasesNotSupportedError`.
|
|
10
|
+
|
|
5
11
|
## [0.2.5] - 2026-05-29
|
|
6
12
|
|
|
7
13
|
### Added
|
data/README.md
CHANGED
|
@@ -128,6 +128,22 @@ By default, the schema files will be saved in the `exwiw` directory. You can spe
|
|
|
128
128
|
OUTPUT_DIR_PATH=custom_directory bundle exec rake exwiw:schema:generate
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
#### Multiple databases
|
|
132
|
+
|
|
133
|
+
If the application uses Rails' multiple-database support (`connects_to`), `schema:generate` buckets models by the database they connect to and writes each database's config files into its own subdirectory of the output directory, named after the database config name (`primary`, `analytics`, ...):
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
exwiw/
|
|
137
|
+
primary/
|
|
138
|
+
shops.json
|
|
139
|
+
users.json
|
|
140
|
+
schema_migrations.json
|
|
141
|
+
analytics/
|
|
142
|
+
analytics_events.json
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Rails-managed tables (`schema_migrations` / `ar_internal_metadata`) are emitted under whichever database actually contains them. Single-database applications are unaffected and continue to write files flat into the output directory.
|
|
146
|
+
|
|
131
147
|
### Configuration
|
|
132
148
|
|
|
133
149
|
This is an example of the one table schema:
|
|
@@ -250,7 +266,7 @@ Constraints:
|
|
|
250
266
|
|
|
251
267
|
- Defining `primary_key`, `columns`, or `belongs_tos` on a rails-managed entry is rejected with `ArgumentError` on load.
|
|
252
268
|
- A rails-managed table cannot be used as `--target-table`.
|
|
253
|
-
-
|
|
269
|
+
- In multi-database setups, the rails-managed entry is emitted under whichever database's connection actually contains the table (see [Multiple databases](#multiple-databases)). The table name itself is still derived from the global `ActiveRecord::Base.schema_migrations_table_name` / `internal_metadata_table_name` (prefix/suffix) accessors.
|
|
254
270
|
|
|
255
271
|
### Bulk insert chunk size
|
|
256
272
|
|
|
@@ -5,8 +5,6 @@ require "json"
|
|
|
5
5
|
|
|
6
6
|
module Exwiw
|
|
7
7
|
class SchemaGenerator
|
|
8
|
-
class MultipleDatabasesNotSupportedError < StandardError; end
|
|
9
|
-
|
|
10
8
|
def self.from_rails_application(output_dir:)
|
|
11
9
|
Rails.application.eager_load!
|
|
12
10
|
new(models: ActiveRecord::Base.descendants, output_dir: output_dir)
|
|
@@ -18,33 +16,53 @@ module Exwiw
|
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
def generate!
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
groups = build_table_groups
|
|
20
|
+
write_groups(groups)
|
|
21
|
+
groups
|
|
24
22
|
end
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
# Returns a Hash keyed by the database name.
|
|
25
|
+
#
|
|
26
|
+
# - Single-database setup: the only key is `nil`, signalling that the table
|
|
27
|
+
# configs should be written flat into `output_dir` (backwards compatible).
|
|
28
|
+
# - Multi-database setup (Rails `connects_to`): one key per database
|
|
29
|
+
# (`connection_db_config.name`, e.g. "primary" / "analytics"), each
|
|
30
|
+
# mapping to that database's table configs. They are written into
|
|
31
|
+
# `output_dir/<db_name>/`.
|
|
32
|
+
def build_table_groups
|
|
27
33
|
models = concrete_models
|
|
28
|
-
|
|
34
|
+
grouped = models.group_by { |model| database_name_for(model) }
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
name: table_name,
|
|
34
|
-
primary_key: representative.primary_key,
|
|
35
|
-
belongs_tos: aggregate_belongs_tos(model_group),
|
|
36
|
-
columns: representative.column_names.map { |name| { name: name } },
|
|
37
|
-
)
|
|
36
|
+
if grouped.size <= 1
|
|
37
|
+
conn = models.empty? ? ActiveRecord::Base.connection : models.first.connection
|
|
38
|
+
return { nil => build_tables_for(models, conn) }
|
|
38
39
|
end
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
grouped.each_with_object({}) do |(db_name, group_models), result|
|
|
42
|
+
conn = group_models.first.connection
|
|
43
|
+
result[db_name] = build_tables_for(group_models, conn)
|
|
44
|
+
end
|
|
41
45
|
end
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
# Backwards-compatible flat list of all table configs. Only meaningful for
|
|
48
|
+
# a single-database setup; for multi-database setups prefer
|
|
49
|
+
# `#build_table_groups` so the database association is preserved.
|
|
50
|
+
def build_tables
|
|
51
|
+
build_table_groups.values.flatten
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def write_groups(groups)
|
|
55
|
+
groups.each do |db_name, tables|
|
|
56
|
+
dir = db_name.nil? ? @output_dir : File.join(@output_dir, db_name)
|
|
57
|
+
write_files(dir, tables)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def write_files(dir, tables)
|
|
62
|
+
FileUtils.mkdir_p(dir)
|
|
45
63
|
|
|
46
64
|
tables.each do |table|
|
|
47
|
-
path = File.join(
|
|
65
|
+
path = File.join(dir, "#{table.name}.json")
|
|
48
66
|
config_to_write =
|
|
49
67
|
if File.exist?(path)
|
|
50
68
|
TableConfig.from(JSON.parse(File.read(path))).merge(table)
|
|
@@ -55,20 +73,31 @@ module Exwiw
|
|
|
55
73
|
end
|
|
56
74
|
end
|
|
57
75
|
|
|
76
|
+
private def build_tables_for(models, conn)
|
|
77
|
+
tables_from_models = models.group_by(&:table_name).map do |table_name, model_group|
|
|
78
|
+
representative = model_group.first
|
|
79
|
+
TableConfig.from_symbol_keys(
|
|
80
|
+
name: table_name,
|
|
81
|
+
primary_key: representative.primary_key,
|
|
82
|
+
belongs_tos: aggregate_belongs_tos(model_group),
|
|
83
|
+
columns: representative.column_names.map { |name| { name: name } },
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
tables_from_models + build_rails_managed_tables(conn)
|
|
88
|
+
end
|
|
89
|
+
|
|
58
90
|
private def concrete_models
|
|
59
91
|
@models.reject(&:abstract_class?).select(&:table_exists?)
|
|
60
92
|
end
|
|
61
93
|
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
#
|
|
68
|
-
|
|
69
|
-
# テーブル名を取り、connection 毎にエントリを生成する必要がある。
|
|
70
|
-
private def build_rails_managed_tables
|
|
71
|
-
conn = ActiveRecord::Base.connection
|
|
94
|
+
# rails-managed テーブル (`schema_migrations` / `ar_internal_metadata`) は
|
|
95
|
+
# モデルクラスを持たないため `ActiveRecord::Base.descendants` からは拾えない。
|
|
96
|
+
# multi-DB 構成では各 connection が独立した migration 履歴テーブルを持つので、
|
|
97
|
+
# 対象 connection を受け取り、その connection 上に該当テーブルが存在する場合のみ
|
|
98
|
+
# エントリを生成する。テーブル名そのものは prefix/suffix を含むグローバル設定
|
|
99
|
+
# (`ActiveRecord::Base.schema_migrations_table_name` 等) から得る。
|
|
100
|
+
private def build_rails_managed_tables(conn)
|
|
72
101
|
result = []
|
|
73
102
|
|
|
74
103
|
schema_migrations_name = ActiveRecord::Base.schema_migrations_table_name
|
|
@@ -108,22 +137,13 @@ module Exwiw
|
|
|
108
137
|
end
|
|
109
138
|
end
|
|
110
139
|
|
|
111
|
-
#
|
|
112
|
-
#
|
|
113
|
-
#
|
|
114
|
-
#
|
|
115
|
-
#
|
|
116
|
-
private def
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
specs = models.map(&:connection_specification_name).uniq
|
|
120
|
-
return if specs.size <= 1
|
|
121
|
-
|
|
122
|
-
raise MultipleDatabasesNotSupportedError, <<~MSG
|
|
123
|
-
exwiw does not yet support Rails multiple-database setup.
|
|
124
|
-
Detected connection specifications: #{specs.inspect}
|
|
125
|
-
Track progress at https://github.com/riseshia/exwiw/issues
|
|
126
|
-
MSG
|
|
140
|
+
# Identifies which database a model belongs to. With Rails multi-DB
|
|
141
|
+
# (`connects_to` backed by `database.yml`), `connection_db_config.name`
|
|
142
|
+
# returns the configuration name ("primary", "analytics", ...) which is
|
|
143
|
+
# stable across roles/shards and makes a natural per-database directory
|
|
144
|
+
# name. Single-database apps all share one name, collapsing into one group.
|
|
145
|
+
private def database_name_for(model)
|
|
146
|
+
model.connection_db_config.name
|
|
127
147
|
end
|
|
128
148
|
end
|
|
129
149
|
end
|
data/lib/exwiw/version.rb
CHANGED