master_data_tool 0.18.0 → 0.19.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 553fcd688f3ae346cc356961473852142c87f0ee66145b9e1892bfac3e230927
4
- data.tar.gz: 64813eea92f8afc4612cdeb19f281c11ecef5537a207a736cd38ef68d57d9adf
3
+ metadata.gz: 5d77c4691ca7880f5b1ab73c4d0e5d424e743cb2973e88cb2fc45e7d15cf7acf
4
+ data.tar.gz: a18d5f0ec46051a0c45db4e369270a5387a827cafa6b17760ead426152a1fd3e
5
5
  SHA512:
6
- metadata.gz: 9b617aed72fbd9bc0a355e81baef951c4f7f3d4cdf3838cf80b7e35533c98ba4fdfc0c01137d6b28e81f4d60798f21c4b81c94f1c53badba689edfe6d9c0c117
7
- data.tar.gz: 0d1daa98e982a6bb918d6dc63dde683b8ce65181337a6fb1754a124d7f93d0e6daa7b25e5cfa5f31a16261c8c4624d6544313a72105dff7746d9df69c28277d5
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 | 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 | 結果の出力をやめる |
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
- | --override_identifier | nil | fixtures/#{override_identifier} のディレクトリにある内容でfixturesを上書きして投入する |
49
+ | --override-identifier | nil | fixtures/#{override_identifier} のディレクトリにある内容でfixturesを上書きして投入する |
50
50
 
51
51
  ```bash
52
52
  bundle exec master_data_tool import
@@ -27,11 +27,13 @@ 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
 
@@ -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
 
@@ -115,7 +119,10 @@ module MasterDataTool
115
119
  return true if import_skip_table?(master_data_file.table_name)
116
120
  return false unless @skip_no_change
117
121
 
118
- !MasterDataTool::MasterDataStatus.master_data_will_change?(master_data_file)
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)
119
126
  end
120
127
 
121
128
  def import_skip_table?(table_name)
@@ -152,6 +159,10 @@ module MasterDataTool
152
159
  pattern = Pathname.new(MasterDataTool.config.master_data_dir).join(@override_identifier).join('*.csv').to_s
153
160
  Pathname.glob(pattern).select(&:file?)
154
161
  end
162
+
163
+ def load_master_data_statuses
164
+ @master_data_statuses = MasterDataTool::MasterDataStatus.fetch_all
165
+ end
155
166
  end
156
167
  end
157
168
  end
@@ -142,9 +142,13 @@ module MasterDataTool
142
142
  scoped.find_each do |record|
143
143
  valid = record.valid?
144
144
  report.append(MasterDataTool::Report::VerifyReport.build_verify_record_report(self, record, valid))
145
+ next if valid
145
146
  next if ignore_fail
146
147
 
147
- raise MasterDataTool::VerifyFailed.new("[#{table_name}] id = #{record.id} is invalid") unless valid
148
+ e = MasterDataTool::VerifyFailed.new("[#{table_name}] id = #{record.id} is invalid")
149
+ e.errors = record.errors
150
+
151
+ raise e
148
152
  end
149
153
  end
150
154
  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
- else
27
- import!(records, validate: true, on_duplicate_key_update: %w[name version], timestamps: true)
36
+ return
28
37
  end
29
- end
30
38
 
31
- # @param [MasterDataTool::MasterDataFile] master_data_file
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)
@@ -7,6 +7,7 @@ module MasterDataTool
7
7
 
8
8
  def print(message)
9
9
  return if @silent
10
+ return if message.blank?
10
11
 
11
12
  MasterDataTool.config.logger.info message
12
13
  puts message
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MasterDataTool
4
- VERSION = "0.18.0"
4
+ VERSION = "0.19.0"
5
5
  end
@@ -1,6 +1,7 @@
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"
@@ -15,9 +16,13 @@ require_relative "master_data_tool/import"
15
16
  module MasterDataTool
16
17
  class Error < StandardError; end
17
18
  class DryRunError < StandardError; end
18
- class VerifyFailed < StandardError; end
19
19
  class NotLoadedError < StandardError; end
20
20
 
21
+ class VerifyFailed < StandardError
22
+ attr_accessor :errors
23
+ delegate :full_messages, to: :errors
24
+ end
25
+
21
26
  class << self
22
27
  def config
23
28
  @config ||= Config.new
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+ set -ex
3
+
4
+ CURRENT=$(cd $(dirname $0);pwd)
5
+
6
+ mysql \
7
+ -u ${DB_USERNAME} \
8
+ -h ${DB_HOST} \
9
+ -p${DB_PASSWORD} \
10
+ --port ${DB_PORT} \
11
+ -e "DROP DATABASE ${DB_NAME}"
@@ -1,4 +1,230 @@
1
+ # TypeProf 0.21.3
2
+
3
+ # Classes
1
4
  module MasterDataTool
2
5
  VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
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.18.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-07-29 00:00:00.000000000 Z
11
+ date: 2022-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -209,6 +209,7 @@ files:
209
209
  - lib/master_data_tool/version.rb
210
210
  - log/test.log
211
211
  - master_data_tool.gemspec
212
+ - scripts/drop_db.sh
212
213
  - scripts/setup.sh
213
214
  - sig/master_data_tool.rbs
214
215
  homepage: https://github.com/taka0125/master_data_tool
@@ -231,7 +232,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
231
232
  - !ruby/object:Gem::Version
232
233
  version: '0'
233
234
  requirements: []
234
- rubygems_version: 3.2.33
235
+ rubygems_version: 3.3.7
235
236
  signing_key:
236
237
  specification_version: 4
237
238
  summary: マスタデータの管理ツール