master_data_tool 0.16.0 → 0.19.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 +4 -4
- data/README.md +11 -11
- data/lib/master_data_tool/config.rb +4 -0
- data/lib/master_data_tool/import/executor.rb +32 -25
- data/lib/master_data_tool/import.rb +0 -1
- data/lib/master_data_tool/master_data.rb +27 -2
- data/lib/master_data_tool/master_data_collection.rb +25 -0
- data/lib/master_data_tool/master_data_file.rb +25 -3
- data/lib/master_data_tool/master_data_file_collection.rb +51 -0
- data/lib/master_data_tool/master_data_status.rb +12 -7
- data/lib/master_data_tool/report/default_printer.rb +1 -0
- data/lib/master_data_tool/version.rb +1 -1
- data/lib/master_data_tool.rb +8 -1
- data/master_data_tool.gemspec +42 -0
- data/scripts/drop_db.sh +11 -0
- data/sig/master_data_tool.rbs +227 -1
- metadata +7 -4
- data/lib/master_data_tool/import/master_data_file_list.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d77c4691ca7880f5b1ab73c4d0e5d424e743cb2973e88cb2fc45e7d15cf7acf
|
4
|
+
data.tar.gz: a18d5f0ec46051a0c45db4e369270a5387a827cafa6b17760ead426152a1fd3e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 644b4a2322932c327a75d1cd955458689e4e08151301cbb1f5782a7465a62bfc80ba823774b0d77b2a525ce9cbd68dd28e6a14b354473608c4a7b61ef4cbf9b1
|
7
|
+
data.tar.gz: 91eb8811ca518eb91311c2d4a50dea7bb778edfa7f106e0d6d09e6bc5b866d4e12c6375936aa31f02f918c73979e9b81fa1038531f1ca9281e6a80d246516aa7
|
data/README.md
CHANGED
@@ -35,18 +35,18 @@ Or install it yourself as:
|
|
35
35
|
|
36
36
|
### マスタデータの投入
|
37
37
|
|
38
|
-
| option
|
39
|
-
|
40
|
-
| --dry-run
|
41
|
-
| --verify
|
42
|
-
| --only-import-tables
|
43
|
-
| --except-import-tables
|
44
|
-
| --only-verify-tables
|
45
|
-
| --except-verify-tables
|
46
|
-
| --skip-no-change
|
47
|
-
| --silent
|
38
|
+
| option | default | 内容 |
|
39
|
+
|---------------------------------| --- |-----------------------------------------------------------------|
|
40
|
+
| --dry-run | true | dry-runモードで実行する(データ変更は行わない) |
|
41
|
+
| --verify | true | データ投入後に全テーブル・全レコードのバリデーションチェックを行う |
|
42
|
+
| --only-import-tables | [] | 指定したテーブルのみデータ投入を行う |
|
43
|
+
| --except-import-tables | [] | 指定したテーブルのデータ投入を行わない |
|
44
|
+
| --only-verify-tables | [] | 指定したテーブルのみ投入後のバリデーションチェックを行う |
|
45
|
+
| --except-verify-tables | [] | 指定したテーブルのバリデーションチェックを行わない |
|
46
|
+
| --skip-no-change | true | CSVファイルに更新がないテーブルをスキップする |
|
47
|
+
| --silent | false | 結果の出力をやめる |
|
48
48
|
| --delete-all-ignore-foreign-key | false | 外部キー制約を無視してレコードを消すかどうか |
|
49
|
-
| --
|
49
|
+
| --override-identifier | nil | fixtures/#{override_identifier} のディレクトリにある内容でfixturesを上書きして投入する |
|
50
50
|
|
51
51
|
```bash
|
52
52
|
bundle exec master_data_tool import
|
@@ -9,12 +9,16 @@ module MasterDataTool
|
|
9
9
|
config_accessor :dump_ignore_columns
|
10
10
|
config_accessor :default_import_options
|
11
11
|
config_accessor :logger
|
12
|
+
config_accessor :preload_associations
|
13
|
+
config_accessor :eager_load_associations
|
12
14
|
|
13
15
|
def initialize
|
14
16
|
self.master_data_dir = nil
|
15
17
|
self.dump_ignore_tables = %w[]
|
16
18
|
self.dump_ignore_columns = %w[]
|
17
19
|
self.default_import_options = {}
|
20
|
+
self.preload_associations = {} # key: Class, value: associations
|
21
|
+
self.eager_load_associations = {} # key: Class, value: associations
|
18
22
|
self.logger = Logger.new(nil)
|
19
23
|
end
|
20
24
|
end
|
@@ -27,23 +27,25 @@ module MasterDataTool
|
|
27
27
|
@override_identifier = override_identifier
|
28
28
|
@report_printer = report_printer
|
29
29
|
@report_printer.silent = silent
|
30
|
+
@master_data_statuses = []
|
30
31
|
end
|
31
32
|
|
32
33
|
def execute
|
33
34
|
ApplicationRecord.transaction do
|
34
35
|
print_execute_options
|
36
|
+
load_master_data_statuses
|
35
37
|
|
36
|
-
|
38
|
+
master_data_collection = build_master_data_collection
|
37
39
|
|
38
|
-
import_all!(
|
39
|
-
verify_all!(
|
40
|
-
save_master_data_statuses!(
|
40
|
+
import_all!(master_data_collection)
|
41
|
+
verify_all!(master_data_collection) if @verify
|
42
|
+
save_master_data_statuses!(master_data_collection)
|
41
43
|
|
42
|
-
print_affected_tables(
|
44
|
+
print_affected_tables(master_data_collection)
|
43
45
|
|
44
46
|
raise DryRunError if @dry_run
|
45
47
|
|
46
|
-
|
48
|
+
master_data_collection
|
47
49
|
end
|
48
50
|
rescue DryRunError
|
49
51
|
puts "[DryRun] end"
|
@@ -51,6 +53,8 @@ module MasterDataTool
|
|
51
53
|
|
52
54
|
private
|
53
55
|
|
56
|
+
attr_reader :master_data_statuses
|
57
|
+
|
54
58
|
def print_execute_options
|
55
59
|
return if @silent
|
56
60
|
|
@@ -61,22 +65,18 @@ module MasterDataTool
|
|
61
65
|
puts "================="
|
62
66
|
end
|
63
67
|
|
64
|
-
def
|
65
|
-
|
66
|
-
MasterDataTool::
|
68
|
+
def build_master_data_collection
|
69
|
+
MasterDataCollection.new.tap do |collection|
|
70
|
+
MasterDataTool::MasterDataFileCollection.new(override_identifier: @override_identifier).each do |master_data_file|
|
67
71
|
load_skip = load_skip_table?(master_data_file)
|
68
|
-
|
69
|
-
|
70
|
-
master_data = MasterData.new(master_data_file, model_klass)
|
71
|
-
master_data.load unless load_skip
|
72
|
-
|
73
|
-
master_data_list << master_data
|
72
|
+
master_data = MasterData.build(master_data_file, load: !load_skip)
|
73
|
+
collection.append(master_data)
|
74
74
|
end
|
75
|
-
end
|
75
|
+
end
|
76
76
|
end
|
77
77
|
|
78
|
-
def import_all!(
|
79
|
-
|
78
|
+
def import_all!(master_data_collection)
|
79
|
+
master_data_collection.each do |master_data|
|
80
80
|
next unless master_data.loaded?
|
81
81
|
next if import_skip_table?(master_data.table_name)
|
82
82
|
|
@@ -85,8 +85,8 @@ module MasterDataTool
|
|
85
85
|
end
|
86
86
|
end
|
87
87
|
|
88
|
-
def verify_all!(
|
89
|
-
|
88
|
+
def verify_all!(master_data_collection)
|
89
|
+
master_data_collection.each do |master_data|
|
90
90
|
next if verify_skip_table?(master_data.table_name)
|
91
91
|
|
92
92
|
report = master_data.verify!(ignore_fail: @dry_run)
|
@@ -94,9 +94,9 @@ module MasterDataTool
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
def save_master_data_statuses!(
|
97
|
+
def save_master_data_statuses!(master_data_collection)
|
98
98
|
records = []
|
99
|
-
|
99
|
+
master_data_collection.each do |master_data|
|
100
100
|
next unless master_data.loaded?
|
101
101
|
|
102
102
|
records << MasterDataTool::MasterDataStatus.build(master_data.master_data_file)
|
@@ -105,8 +105,8 @@ module MasterDataTool
|
|
105
105
|
MasterDataTool::MasterDataStatus.import_records!(records, dry_run: @dry_run)
|
106
106
|
end
|
107
107
|
|
108
|
-
def print_affected_tables(
|
109
|
-
|
108
|
+
def print_affected_tables(master_data_collection)
|
109
|
+
master_data_collection.each do |master_data|
|
110
110
|
next unless master_data.loaded?
|
111
111
|
next unless master_data.affected?
|
112
112
|
|
@@ -119,7 +119,10 @@ module MasterDataTool
|
|
119
119
|
return true if import_skip_table?(master_data_file.table_name)
|
120
120
|
return false unless @skip_no_change
|
121
121
|
|
122
|
-
|
122
|
+
master_data_status = master_data_statuses.dig(master_data_file.table_name)
|
123
|
+
return false unless master_data_status
|
124
|
+
|
125
|
+
!master_data_status.will_change?(master_data_file)
|
123
126
|
end
|
124
127
|
|
125
128
|
def import_skip_table?(table_name)
|
@@ -156,6 +159,10 @@ module MasterDataTool
|
|
156
159
|
pattern = Pathname.new(MasterDataTool.config.master_data_dir).join(@override_identifier).join('*.csv').to_s
|
157
160
|
Pathname.glob(pattern).select(&:file?)
|
158
161
|
end
|
162
|
+
|
163
|
+
def load_master_data_statuses
|
164
|
+
@master_data_statuses = MasterDataTool::MasterDataStatus.fetch_all
|
165
|
+
end
|
159
166
|
end
|
160
167
|
end
|
161
168
|
end
|
@@ -19,6 +19,15 @@ module MasterDataTool
|
|
19
19
|
@deleted_records = []
|
20
20
|
end
|
21
21
|
|
22
|
+
class << self
|
23
|
+
def build(master_data_file, load: false)
|
24
|
+
model_klass = Object.const_get(master_data_file.table_name.classify)
|
25
|
+
new(master_data_file, model_klass).tap do |record|
|
26
|
+
record.load if load
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
22
31
|
def basename
|
23
32
|
@master_data_file.basename
|
24
33
|
end
|
@@ -126,12 +135,20 @@ module MasterDataTool
|
|
126
135
|
|
127
136
|
def verify!(ignore_fail: false)
|
128
137
|
MasterDataTool::Report::VerifyReport.new(self).tap do |report|
|
129
|
-
@model_klass.all
|
138
|
+
scoped = @model_klass.all
|
139
|
+
scoped = scoped.preload(preload_associations) if preload_associations
|
140
|
+
scoped = scoped.eager_load(eager_load_associations) if eager_load_associations
|
141
|
+
|
142
|
+
scoped.find_each do |record|
|
130
143
|
valid = record.valid?
|
131
144
|
report.append(MasterDataTool::Report::VerifyReport.build_verify_record_report(self, record, valid))
|
145
|
+
next if valid
|
132
146
|
next if ignore_fail
|
133
147
|
|
134
|
-
|
148
|
+
e = MasterDataTool::VerifyFailed.new("[#{table_name}] id = #{record.id} is invalid")
|
149
|
+
e.errors = record.errors
|
150
|
+
|
151
|
+
raise e
|
135
152
|
end
|
136
153
|
end
|
137
154
|
end
|
@@ -145,6 +162,14 @@ module MasterDataTool
|
|
145
162
|
|
146
163
|
private
|
147
164
|
|
165
|
+
def preload_associations
|
166
|
+
@preload_associations ||= MasterDataTool.config.preload_associations.dig(@model_klass.to_s.to_sym)
|
167
|
+
end
|
168
|
+
|
169
|
+
def eager_load_associations
|
170
|
+
@eager_load_associations ||= MasterDataTool.config.eager_load_associations.dig(@model_klass.to_s.to_sym)
|
171
|
+
end
|
172
|
+
|
148
173
|
def build_records_from_csv(csv, old_records_by_id)
|
149
174
|
{}.tap do |records|
|
150
175
|
csv.each do |row|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MasterDataTool
|
4
|
+
class MasterDataCollection
|
5
|
+
def initialize
|
6
|
+
@collection = []
|
7
|
+
end
|
8
|
+
|
9
|
+
def append(master_data)
|
10
|
+
@collection << master_data
|
11
|
+
end
|
12
|
+
|
13
|
+
def each
|
14
|
+
return enum_for(:each) unless block_given?
|
15
|
+
|
16
|
+
@collection.sort_by(&:basename).each do |master_data|
|
17
|
+
yield master_data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_a
|
22
|
+
each.to_a
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,13 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module MasterDataTool
|
3
|
-
class MasterDataFile
|
3
|
+
class MasterDataFile
|
4
|
+
attr_reader :table_name, :path, :override_identifier
|
5
|
+
|
4
6
|
def initialize(table_name, path, override_identifier)
|
5
|
-
|
7
|
+
@table_name = table_name
|
8
|
+
@path = path
|
9
|
+
@override_identifier = override_identifier
|
6
10
|
freeze
|
7
11
|
end
|
8
12
|
|
13
|
+
class << self
|
14
|
+
def build(path, override_identifier)
|
15
|
+
table_name = MasterDataTool.resolve_table_name(path, override_identifier)
|
16
|
+
new(table_name, path, override_identifier)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
9
20
|
def basename
|
10
|
-
|
21
|
+
@path.basename
|
22
|
+
end
|
23
|
+
|
24
|
+
def ==(other)
|
25
|
+
other.class === self &&
|
26
|
+
other.hash == hash
|
27
|
+
end
|
28
|
+
|
29
|
+
alias eql? ==
|
30
|
+
|
31
|
+
def hash
|
32
|
+
[@table_name, @path, @override_identifier].join.hash
|
11
33
|
end
|
12
34
|
end
|
13
35
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MasterDataTool
|
4
|
+
class MasterDataFileCollection
|
5
|
+
def initialize(override_identifier: nil)
|
6
|
+
@override_identifier = override_identifier
|
7
|
+
@collection = build
|
8
|
+
freeze
|
9
|
+
end
|
10
|
+
|
11
|
+
def each
|
12
|
+
return enum_for(:each) unless block_given?
|
13
|
+
|
14
|
+
@collection.each do |file|
|
15
|
+
yield file
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_a
|
20
|
+
each.to_a
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def build
|
26
|
+
files = extract_master_data_csv_paths.presence&.index_by(&:table_name)
|
27
|
+
overridden_files = overridden_master_data_csv_paths.presence&.index_by(&:table_name) || {}
|
28
|
+
|
29
|
+
table_names = (files.keys + overridden_files.keys).uniq
|
30
|
+
table_names.map do |table_name|
|
31
|
+
overridden_files[table_name] || files[table_name]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def extract_master_data_csv_paths
|
36
|
+
pattern = Pathname.new(MasterDataTool.config.master_data_dir).join('*.csv').to_s
|
37
|
+
Pathname.glob(pattern).select(&:file?).map do |path|
|
38
|
+
MasterDataFile.build(path, nil)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def overridden_master_data_csv_paths
|
43
|
+
return [] if @override_identifier.blank?
|
44
|
+
|
45
|
+
pattern = Pathname.new(MasterDataTool.config.master_data_dir).join(@override_identifier).join('*.csv').to_s
|
46
|
+
Pathname.glob(pattern).select(&:file?).map do |path|
|
47
|
+
MasterDataFile.build(path, @override_identifier)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -14,7 +14,17 @@ module MasterDataTool
|
|
14
14
|
validates :version,
|
15
15
|
presence: true
|
16
16
|
|
17
|
+
def will_change?(master_data_file)
|
18
|
+
raise unless name == master_data_file.table_name
|
19
|
+
|
20
|
+
version != self.class.decide_version(master_data_file.path)
|
21
|
+
end
|
22
|
+
|
17
23
|
class << self
|
24
|
+
def fetch_all
|
25
|
+
all.index_by(&:name)
|
26
|
+
end
|
27
|
+
|
18
28
|
def build(master_data_file)
|
19
29
|
version = decide_version(master_data_file.path)
|
20
30
|
new(name: MasterDataTool.resolve_table_name(master_data_file.path, master_data_file.override_identifier), version: version)
|
@@ -23,15 +33,10 @@ module MasterDataTool
|
|
23
33
|
def import_records!(records, dry_run: true)
|
24
34
|
if dry_run
|
25
35
|
pp records
|
26
|
-
|
27
|
-
import!(records, validate: true, on_duplicate_key_update: %w[name version], timestamps: true)
|
36
|
+
return
|
28
37
|
end
|
29
|
-
end
|
30
38
|
|
31
|
-
|
32
|
-
def master_data_will_change?(master_data_file)
|
33
|
-
new_version = decide_version(master_data_file.path)
|
34
|
-
!where(name: master_data_file.table_name, version: new_version).exists?
|
39
|
+
import!(records, validate: true, on_duplicate_key_update: %w[name version], timestamps: true)
|
35
40
|
end
|
36
41
|
|
37
42
|
def decide_version(csv_path)
|
data/lib/master_data_tool.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'csv'
|
4
|
+
require 'socket'
|
4
5
|
require_relative "master_data_tool/version"
|
5
6
|
require_relative "master_data_tool/config"
|
6
7
|
require_relative "master_data_tool/master_data_status"
|
7
8
|
require_relative "master_data_tool/master_data_file"
|
9
|
+
require_relative "master_data_tool/master_data_file_collection"
|
8
10
|
require_relative "master_data_tool/master_data"
|
11
|
+
require_relative "master_data_tool/master_data_collection"
|
9
12
|
require_relative "master_data_tool/report"
|
10
13
|
require_relative "master_data_tool/dump/executor"
|
11
14
|
require_relative "master_data_tool/import"
|
@@ -13,9 +16,13 @@ require_relative "master_data_tool/import"
|
|
13
16
|
module MasterDataTool
|
14
17
|
class Error < StandardError; end
|
15
18
|
class DryRunError < StandardError; end
|
16
|
-
class VerifyFailed < StandardError; end
|
17
19
|
class NotLoadedError < StandardError; end
|
18
20
|
|
21
|
+
class VerifyFailed < StandardError
|
22
|
+
attr_accessor :errors
|
23
|
+
delegate :full_messages, to: :errors
|
24
|
+
end
|
25
|
+
|
19
26
|
class << self
|
20
27
|
def config
|
21
28
|
@config ||= Config.new
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/master_data_tool/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "master_data_tool"
|
7
|
+
spec.version = MasterDataTool::VERSION
|
8
|
+
spec.authors = ["Takahiro Ooishi"]
|
9
|
+
spec.email = ["taka0125@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "マスタデータの管理ツール"
|
12
|
+
spec.description = "システムが稼働する上で最初から必要なデータ(マスタデータ)を管理するツールです。"
|
13
|
+
spec.homepage = "https://github.com/taka0125/master_data_tool"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
24
|
+
end
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_development_dependency 'rspec'
|
31
|
+
spec.add_development_dependency 'mysql2'
|
32
|
+
spec.add_development_dependency 'psych', '~> 3.1'
|
33
|
+
spec.add_development_dependency 'appraisal'
|
34
|
+
spec.add_development_dependency 'ridgepole'
|
35
|
+
spec.add_development_dependency 'database_cleaner-active_record'
|
36
|
+
spec.add_development_dependency 'standalone_activerecord_boot_loader'
|
37
|
+
|
38
|
+
spec.add_dependency 'activerecord', '>= 5.1.7'
|
39
|
+
spec.add_dependency 'activesupport'
|
40
|
+
spec.add_dependency 'thor'
|
41
|
+
spec.add_dependency 'activerecord-import'
|
42
|
+
end
|
data/scripts/drop_db.sh
ADDED
data/sig/master_data_tool.rbs
CHANGED
@@ -1,4 +1,230 @@
|
|
1
|
+
# TypeProf 0.21.3
|
2
|
+
|
3
|
+
# Classes
|
1
4
|
module MasterDataTool
|
2
5
|
VERSION: String
|
3
|
-
|
6
|
+
self.@config: Config
|
7
|
+
|
8
|
+
def self.config: -> Config
|
9
|
+
def self.configure: -> untyped
|
10
|
+
def self.resolve_table_name: (Pathname csv_path, String? override_identifier) -> String
|
11
|
+
|
12
|
+
class Config
|
13
|
+
def initialize: -> void
|
14
|
+
end
|
15
|
+
|
16
|
+
class MasterDataStatus
|
17
|
+
def will_change?: (MasterDataFile master_data_file) -> bool
|
18
|
+
def self.fetch_all: -> Hash[String,MasterDataStatus]
|
19
|
+
def self.build: (MasterDataFile master_data_file) -> MasterDataStatus
|
20
|
+
def self.import_records!: (Array[MasterDataStatus] records, dry_run: bool) -> Array[MasterDataStatus]
|
21
|
+
def self.master_data_will_change?: (MasterDataFile master_data_file) -> bool
|
22
|
+
def self.decide_version: (Pathname csv_path) -> String
|
23
|
+
end
|
24
|
+
|
25
|
+
class MasterDataFile
|
26
|
+
attr_reader table_name: String
|
27
|
+
attr_reader path: Pathname
|
28
|
+
attr_reader override_identifier: String?
|
29
|
+
def initialize: (String table_name, Pathname path, String? override_identifier) -> void
|
30
|
+
def self.build: (Pathname path, String? override_identifier) -> MasterDataFile
|
31
|
+
def basename: -> Pathname
|
32
|
+
def ==: (untyped other) -> bool
|
33
|
+
alias eql? ==
|
34
|
+
def hash: -> Integer
|
35
|
+
end
|
36
|
+
|
37
|
+
class MasterDataFileCollection
|
38
|
+
@override_identifier: String?
|
39
|
+
@collection: Array[MasterDataFile]
|
40
|
+
|
41
|
+
def initialize: (override_identifier: String?) -> void
|
42
|
+
def each: ?{ -> Array[MasterDataFile] } -> Enumerator[bot, untyped]
|
43
|
+
def to_a: -> Array[MasterDataFile]
|
44
|
+
|
45
|
+
private
|
46
|
+
def build: -> Array[MasterDataFile]
|
47
|
+
def extract_master_data_csv_paths: -> Array[MasterDataFile]
|
48
|
+
def overridden_master_data_csv_paths: -> Array[MasterDataFile]
|
49
|
+
end
|
50
|
+
|
51
|
+
class MasterData
|
52
|
+
@loaded: bool
|
53
|
+
@affected: bool
|
54
|
+
@preload_associations: Array[untyped]
|
55
|
+
@eager_load_associations: Array[untyped]
|
56
|
+
|
57
|
+
attr_reader master_data_file: MasterDataFile
|
58
|
+
attr_reader model_klass: untyped
|
59
|
+
attr_reader columns: Array[String]
|
60
|
+
attr_reader new_records: Array[untyped]
|
61
|
+
def new_records: -> Array[untyped]
|
62
|
+
attr_reader updated_records: Array[untyped]
|
63
|
+
def updated_records: -> Array[untyped]
|
64
|
+
attr_reader no_change_records: Array[untyped]
|
65
|
+
def no_change_records: -> Array[untyped]
|
66
|
+
attr_reader deleted_records: Array[untyped]
|
67
|
+
def deleted_records: -> Array[untyped]
|
68
|
+
attr_reader before_count: Integer
|
69
|
+
def before_count: -> Integer
|
70
|
+
attr_reader after_count: Integer
|
71
|
+
def after_count: -> Integer
|
72
|
+
def initialize: (MasterDataFile master_data_file, untyped model_klass) -> void
|
73
|
+
def self.build: (MasterDataFile master_data_file, ?load: bool) -> MasterData
|
74
|
+
def basename: -> Pathname
|
75
|
+
def load: -> true
|
76
|
+
def import_records: -> Array[untyped]
|
77
|
+
def affected_records: -> Array[untyped]
|
78
|
+
def loaded?: -> bool
|
79
|
+
def affected?: -> bool?
|
80
|
+
def table_name: -> String
|
81
|
+
def import!: (?dry_run: true, ?delete_all_ignore_foreign_key: false) -> Report::ImportReport
|
82
|
+
def verify!: (?ignore_fail: bool) -> Report::VerifyReport
|
83
|
+
def print_affected_table: -> Report::PrintAffectedTableReport?
|
84
|
+
|
85
|
+
private
|
86
|
+
def preload_associations: -> Array[untyped]
|
87
|
+
def eager_load_associations: -> Array[untyped]
|
88
|
+
def build_records_from_csv: (Array[Array[String?]] csv, Hash[Integer, untyped] old_records_by_id) -> Hash[Integer, untyped]
|
89
|
+
def enable_foreign_key_checks: -> untyped
|
90
|
+
def disable_foreign_key_checks: -> untyped
|
91
|
+
end
|
92
|
+
|
93
|
+
class MasterDataCollection
|
94
|
+
@collection: Array[MasterData]
|
95
|
+
|
96
|
+
def initialize: -> void
|
97
|
+
def append: (MasterData master_data) -> Array[MasterData]
|
98
|
+
def each: ?{ (MasterData) -> (Array[MasterDataStatus | {operation: :verify, table_name: untyped, valid: untyped, id: untyped}]?) } -> (Array[MasterData] | Enumerator[MasterData, untyped] | Enumerator[untyped, untyped])
|
99
|
+
def to_a: -> Array[MasterData]
|
100
|
+
end
|
101
|
+
|
102
|
+
module Report
|
103
|
+
module Printer
|
104
|
+
attr_accessor silent: false
|
105
|
+
def initialize: (?silent: false) -> void
|
106
|
+
def print: (String message) -> nil
|
107
|
+
end
|
108
|
+
|
109
|
+
class DefaultPrinter
|
110
|
+
include Printer
|
111
|
+
|
112
|
+
def print: (String message) -> nil
|
113
|
+
end
|
114
|
+
|
115
|
+
module Core
|
116
|
+
def initialize: (MasterData master_data) -> void
|
117
|
+
def print: (Printer printer) -> untyped
|
118
|
+
|
119
|
+
private
|
120
|
+
def convert_to_ltsv: ({operation: :affected_table | :verify, table_name: untyped, valid: untyped, id: untyped} items) -> String
|
121
|
+
end
|
122
|
+
|
123
|
+
class ImportReport
|
124
|
+
include Core
|
125
|
+
@master_data: MasterData
|
126
|
+
|
127
|
+
attr_reader reports: Array[untyped]
|
128
|
+
def reports: -> Array[untyped]
|
129
|
+
def print: (Printer printer) -> untyped
|
130
|
+
|
131
|
+
private
|
132
|
+
def count_report: -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
|
133
|
+
def new_records_report: -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
|
134
|
+
def updated_records_report: -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
|
135
|
+
def no_change_records_report: -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
|
136
|
+
def deleted_records_report: -> Hash[Symbol, Array[Hash[Symbol, untyped]]]
|
137
|
+
end
|
138
|
+
|
139
|
+
class VerifyReport
|
140
|
+
include Core
|
141
|
+
@master_data: MasterData
|
142
|
+
|
143
|
+
attr_reader reports: Array[{operation: :verify, table_name: untyped, valid: untyped, id: untyped}]
|
144
|
+
def initialize: (MasterData master_data) -> void
|
145
|
+
def append: ({operation: :verify, table_name: untyped, valid: untyped, id: untyped} verify_record_report) -> Array[{operation: :verify, table_name: untyped, valid: untyped, id: untyped}]
|
146
|
+
def print: (Printer printer) -> Array[{operation: :verify, table_name: untyped, valid: untyped, id: untyped}]
|
147
|
+
def self.build_verify_record_report: (MasterData master_data, untyped record, untyped valid) -> {operation: :verify, table_name: untyped, valid: untyped, id: untyped}
|
148
|
+
end
|
149
|
+
|
150
|
+
class PrintAffectedTableReport
|
151
|
+
include Core
|
152
|
+
@master_data: MasterData
|
153
|
+
|
154
|
+
def print: (Printer printer) -> nil
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
module Dump
|
159
|
+
class Executor
|
160
|
+
DEFAULT_IGNORE_TABLES: [String, String, String]
|
161
|
+
DEFAULT_IGNORE_COLUMNS: [String, String]
|
162
|
+
@ignore_empty_table: bool
|
163
|
+
@ignore_tables: Array[String]
|
164
|
+
@ignore_column_names: Array[String]
|
165
|
+
@only_tables: Array[String]
|
166
|
+
@verbose: bool
|
167
|
+
|
168
|
+
def initialize: (ignore_empty_table: bool, ignore_tables: Array[String], ignore_column_names: Array[String], only_tables: Array[String], verbose: bool) -> void
|
169
|
+
def execute: -> Array[untyped]
|
170
|
+
|
171
|
+
private
|
172
|
+
def print_message: (String message) -> nil
|
173
|
+
def dump_to_csv: (untyped table) -> nil
|
174
|
+
def ignore?: (untyped model_klass) -> false
|
175
|
+
|
176
|
+
class Error < Struct[untyped]
|
177
|
+
attr_accessor table(): untyped
|
178
|
+
attr_accessor exception(): nil
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
module Import
|
184
|
+
class Executor
|
185
|
+
@dry_run: bool
|
186
|
+
@verify: bool
|
187
|
+
@only_import_tables: Array[String]
|
188
|
+
@except_import_tables: Array[String]
|
189
|
+
@only_verify_tables: Array[String]
|
190
|
+
@except_verify_tables: Array[String]
|
191
|
+
@skip_no_change: bool
|
192
|
+
@silent: bool
|
193
|
+
@delete_all_ignore_foreign_key: bool
|
194
|
+
@override_identifier: String?
|
195
|
+
@report_printer: Report::DefaultPrinter
|
196
|
+
@master_data_statuses: [MasterDataStatus]
|
197
|
+
|
198
|
+
def initialize: (dry_run: bool, verify: bool, only_import_tables: Array[String], except_import_tables: Array[String], only_verify_tables: Array[String], except_verify_tables: Array[String], skip_no_change: bool, silent: bool, delete_all_ignore_foreign_key: bool, override_identifier: String?, report_printer: Report::Printer) -> void
|
199
|
+
def execute: -> nil
|
200
|
+
|
201
|
+
private
|
202
|
+
def print_execute_options: -> nil
|
203
|
+
def build_master_data_collection: -> MasterDataCollection
|
204
|
+
def import_all!: (MasterDataCollection master_data_collection) -> (Array[MasterData] | Enumerator[MasterData, untyped] | Enumerator[untyped, untyped])
|
205
|
+
def verify_all!: (MasterDataCollection master_data_collection) -> (Array[MasterData] | Enumerator[MasterData, untyped] | Enumerator[untyped, untyped])
|
206
|
+
def save_master_data_statuses!: (MasterDataCollection master_data_collection) -> Array[MasterDataStatus]
|
207
|
+
def print_affected_tables: (MasterDataCollection master_data_collection) -> (Array[MasterData] | Enumerator[MasterData, untyped] | Enumerator[untyped, untyped])
|
208
|
+
def load_skip_table?: (untyped master_data_file) -> bool
|
209
|
+
def import_skip_table?: (untyped table_name) -> bool
|
210
|
+
def verify_skip_table?: (untyped table_name) -> bool
|
211
|
+
def need_skip_table?: (untyped table_name, Array[untyped] only, Array[untyped] except) -> bool
|
212
|
+
def extract_master_data_csv_paths: -> Array[Pathname]
|
213
|
+
def overridden_master_data_csv_paths: -> Array[Pathname]
|
214
|
+
def master_data_statuses: -> untyped
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
class Error < StandardError
|
219
|
+
end
|
220
|
+
|
221
|
+
class DryRunError < StandardError
|
222
|
+
end
|
223
|
+
|
224
|
+
class NotLoadedError < StandardError
|
225
|
+
end
|
226
|
+
|
227
|
+
class VerifyFailed < StandardError
|
228
|
+
attr_accessor errors: untyped
|
229
|
+
end
|
4
230
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: master_data_tool
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Takahiro Ooishi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -194,9 +194,10 @@ files:
|
|
194
194
|
- lib/master_data_tool/dump/executor.rb
|
195
195
|
- lib/master_data_tool/import.rb
|
196
196
|
- lib/master_data_tool/import/executor.rb
|
197
|
-
- lib/master_data_tool/import/master_data_file_list.rb
|
198
197
|
- lib/master_data_tool/master_data.rb
|
198
|
+
- lib/master_data_tool/master_data_collection.rb
|
199
199
|
- lib/master_data_tool/master_data_file.rb
|
200
|
+
- lib/master_data_tool/master_data_file_collection.rb
|
200
201
|
- lib/master_data_tool/master_data_status.rb
|
201
202
|
- lib/master_data_tool/report.rb
|
202
203
|
- lib/master_data_tool/report/core.rb
|
@@ -207,6 +208,8 @@ files:
|
|
207
208
|
- lib/master_data_tool/report/verify_report.rb
|
208
209
|
- lib/master_data_tool/version.rb
|
209
210
|
- log/test.log
|
211
|
+
- master_data_tool.gemspec
|
212
|
+
- scripts/drop_db.sh
|
210
213
|
- scripts/setup.sh
|
211
214
|
- sig/master_data_tool.rbs
|
212
215
|
homepage: https://github.com/taka0125/master_data_tool
|
@@ -229,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
229
232
|
- !ruby/object:Gem::Version
|
230
233
|
version: '0'
|
231
234
|
requirements: []
|
232
|
-
rubygems_version: 3.
|
235
|
+
rubygems_version: 3.3.7
|
233
236
|
signing_key:
|
234
237
|
specification_version: 4
|
235
238
|
summary: マスタデータの管理ツール
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module MasterDataTool
|
4
|
-
module Import
|
5
|
-
class MasterDataFileList
|
6
|
-
Result = Struct.new(:table_name, :path, :override_identifier)
|
7
|
-
|
8
|
-
def initialize(override_identifier: nil)
|
9
|
-
@override_identifier = override_identifier
|
10
|
-
end
|
11
|
-
|
12
|
-
def build
|
13
|
-
files = extract_master_data_csv_paths.presence&.index_by(&:table_name)
|
14
|
-
overridden_files = overridden_master_data_csv_paths.presence&.index_by(&:table_name) || {}
|
15
|
-
|
16
|
-
table_names = (files.keys + overridden_files.keys).uniq
|
17
|
-
table_names.map do |table_name|
|
18
|
-
overridden_files[table_name] || files[table_name]
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def extract_master_data_csv_paths
|
25
|
-
pattern = Pathname.new(MasterDataTool.config.master_data_dir).join('*.csv').to_s
|
26
|
-
Pathname.glob(pattern).select(&:file?).map do |path|
|
27
|
-
table_name = MasterDataTool.resolve_table_name(path, nil)
|
28
|
-
MasterDataTool::MasterDataFile.new(table_name, path, nil)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def overridden_master_data_csv_paths
|
33
|
-
return [] if @override_identifier.blank?
|
34
|
-
|
35
|
-
pattern = Pathname.new(MasterDataTool.config.master_data_dir).join(@override_identifier).join('*.csv').to_s
|
36
|
-
Pathname.glob(pattern).select(&:file?).map do |path|
|
37
|
-
table_name = MasterDataTool.resolve_table_name(path, @override_identifier)
|
38
|
-
MasterDataTool::MasterDataFile.new(table_name, path, @override_identifier)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|