nicker_pocker 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +71 -0
- data/lib/nicker_pocker/command.rb +149 -0
- data/lib/nicker_pocker/format/detail.rb +152 -0
- data/lib/nicker_pocker/format/operator.rb +88 -0
- data/lib/nicker_pocker/format/prototype.rb +242 -0
- data/lib/nicker_pocker/grouping.rb +82 -0
- data/lib/nicker_pocker/version.rb +1 -1
- data/lib/nicker_pocker.rb +5 -2
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74a52c39ca930e3720480a937ad3decec09f0ea61b13bc99fecceb7d258acfa7
|
4
|
+
data.tar.gz: b79e0dd5a16e4e62236234708371787abfc4dede1e54a58b3eb8298d934fdcf8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8c7e7d4ee9bee1c8b102627626aeb1803e9ecf015c163a8fb527aa0fa760f42237c92d652d45ce9338e8d11ffeef1e3e76b8803ffaddaa785c7a3c43037a6470
|
7
|
+
data.tar.gz: ca79c04b1fddc0faba5818b637c029103bcf81a76ecc6b1c70732c33a158090904412173da305e1864fc072f19e83fa92575cd0ad64732d83df8b47980dab3a0
|
data/Gemfile
CHANGED
data/Gemfile.lock
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
nicker_pocker (0.1.2.3)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
activesupport (7.0.4.3)
|
10
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
11
|
+
i18n (>= 1.6, < 2)
|
12
|
+
minitest (>= 5.1)
|
13
|
+
tzinfo (~> 2.0)
|
14
|
+
ast (2.4.2)
|
15
|
+
concurrent-ruby (1.2.2)
|
16
|
+
diff-lcs (1.5.0)
|
17
|
+
factory_bot (6.2.1)
|
18
|
+
activesupport (>= 5.0.0)
|
19
|
+
i18n (1.12.0)
|
20
|
+
concurrent-ruby (~> 1.0)
|
21
|
+
json (2.6.3)
|
22
|
+
minitest (5.18.0)
|
23
|
+
parallel (1.22.1)
|
24
|
+
parser (3.2.2.0)
|
25
|
+
ast (~> 2.4.1)
|
26
|
+
rainbow (3.1.1)
|
27
|
+
rake (13.0.6)
|
28
|
+
regexp_parser (2.7.0)
|
29
|
+
rexml (3.2.5)
|
30
|
+
rspec (3.12.0)
|
31
|
+
rspec-core (~> 3.12.0)
|
32
|
+
rspec-expectations (~> 3.12.0)
|
33
|
+
rspec-mocks (~> 3.12.0)
|
34
|
+
rspec-core (3.12.1)
|
35
|
+
rspec-support (~> 3.12.0)
|
36
|
+
rspec-expectations (3.12.2)
|
37
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
38
|
+
rspec-support (~> 3.12.0)
|
39
|
+
rspec-mocks (3.12.5)
|
40
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
+
rspec-support (~> 3.12.0)
|
42
|
+
rspec-support (3.12.0)
|
43
|
+
rubocop (1.50.1)
|
44
|
+
json (~> 2.3)
|
45
|
+
parallel (~> 1.10)
|
46
|
+
parser (>= 3.2.0.0)
|
47
|
+
rainbow (>= 2.2.2, < 4.0)
|
48
|
+
regexp_parser (>= 1.8, < 3.0)
|
49
|
+
rexml (>= 3.2.5, < 4.0)
|
50
|
+
rubocop-ast (>= 1.28.0, < 2.0)
|
51
|
+
ruby-progressbar (~> 1.7)
|
52
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
53
|
+
rubocop-ast (1.28.0)
|
54
|
+
parser (>= 3.2.1.0)
|
55
|
+
ruby-progressbar (1.13.0)
|
56
|
+
tzinfo (2.0.6)
|
57
|
+
concurrent-ruby (~> 1.0)
|
58
|
+
unicode-display_width (2.4.2)
|
59
|
+
|
60
|
+
PLATFORMS
|
61
|
+
x86_64-darwin-21
|
62
|
+
|
63
|
+
DEPENDENCIES
|
64
|
+
factory_bot
|
65
|
+
nicker_pocker!
|
66
|
+
rake (~> 13.0)
|
67
|
+
rspec (~> 3.0)
|
68
|
+
rubocop (~> 1.21)
|
69
|
+
|
70
|
+
BUNDLED WITH
|
71
|
+
2.4.8
|
@@ -0,0 +1,149 @@
|
|
1
|
+
# 指定オプションに基づいて処理実行
|
2
|
+
require 'fileutils'
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
module NickerPocker
|
6
|
+
MIGRATE_METHODS =
|
7
|
+
Format::Operator::PROTOTYPE_METHODS +
|
8
|
+
Format::Operator::DETAIL_METHODS
|
9
|
+
|
10
|
+
class Command
|
11
|
+
class << self
|
12
|
+
def exec(options = {})
|
13
|
+
new(options).run
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# 各設定をセット
|
18
|
+
def initialize(options)
|
19
|
+
@options = options
|
20
|
+
|
21
|
+
# 初期値設定
|
22
|
+
@options[:input] ||= './db/migrate/'
|
23
|
+
@options[:output] ||= './nicker_pocker/'
|
24
|
+
@options[:format] ||= :csv
|
25
|
+
end
|
26
|
+
|
27
|
+
# 実行
|
28
|
+
def run
|
29
|
+
return if Dir.glob("#{@options[:input]}*\.rb").empty?
|
30
|
+
|
31
|
+
output(read_data)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# 対象マイグレーションファイルを読み込み
|
37
|
+
#
|
38
|
+
# @return [Array]
|
39
|
+
def read_data
|
40
|
+
temp_data = {}
|
41
|
+
|
42
|
+
Dir::foreach(@options[:input]) do |file_name|
|
43
|
+
next if ['.', '..'].include?(file_name)
|
44
|
+
|
45
|
+
File.open(@options[:input] + file_name) do |f|
|
46
|
+
temp_data[file_name.to_i] = f.readlines.each(&:strip!)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# migrationファイルの実行順に並べ替える
|
51
|
+
temp_data_list = temp_data.sort.to_h.values
|
52
|
+
temp_data_list.flatten!.select! { |row| target_data?(row) }.compact!
|
53
|
+
|
54
|
+
data_list = necessary_data(temp_data_list)
|
55
|
+
|
56
|
+
groups = Grouping.exec(data_list)
|
57
|
+
Format::Operator.exec(groups)
|
58
|
+
end
|
59
|
+
|
60
|
+
# 対象データ判定
|
61
|
+
#
|
62
|
+
# @params [String] row
|
63
|
+
# @return [Boolean]
|
64
|
+
def target_data?(row)
|
65
|
+
return true if /^t\..*|^def\s.*/.match(row)
|
66
|
+
|
67
|
+
MIGRATE_METHODS.each do |method_name|
|
68
|
+
return true if /#{method_name.to_s}\s/.match(row)
|
69
|
+
end
|
70
|
+
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
# 必要なデータを抽出
|
75
|
+
#
|
76
|
+
# @params [Array] data_list
|
77
|
+
# @return [Array]
|
78
|
+
def necessary_data(temp_data_list)
|
79
|
+
data_list = data_list(temp_data_list)
|
80
|
+
necessary_data_list = []
|
81
|
+
pattern = MIGRATE_METHODS.map(&:to_s).join('|')
|
82
|
+
scan_pattern = Regexp.new(".*?[#{pattern}].*")
|
83
|
+
|
84
|
+
# グルーピングしやすいように整形
|
85
|
+
data_list.each_with_index do |data, index|
|
86
|
+
pattern_match_list = data.map do |content|
|
87
|
+
scan_list = content.scan(scan_pattern)
|
88
|
+
scan_list if scan_list.any?
|
89
|
+
end.compact
|
90
|
+
|
91
|
+
# 同じファイルに複数のmigrationメソッドが記載されている場合の対応
|
92
|
+
if pattern_match_list.length > 1
|
93
|
+
sub_list = []
|
94
|
+
pattern_match_list.each do |pattern_match|
|
95
|
+
if pattern_match.first.match?(/#{pattern}/)
|
96
|
+
sub_list.push([*pattern_match])
|
97
|
+
else
|
98
|
+
sub_list.last.push(*pattern_match)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
necessary_data_list.push(sub_list)
|
103
|
+
else
|
104
|
+
necessary_data_list.push(pattern_match_list)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
necessary_data_list
|
109
|
+
end
|
110
|
+
|
111
|
+
def data_list(temp_data_list)
|
112
|
+
data_list = []
|
113
|
+
methods_contents_list = []
|
114
|
+
|
115
|
+
# def ごとの配列に格納
|
116
|
+
temp_data_list.each do |data|
|
117
|
+
if /^def\s.*/.match(data)
|
118
|
+
data_list.push(methods_contents_list) if methods_contents_list.any?
|
119
|
+
methods_contents_list = []
|
120
|
+
end
|
121
|
+
|
122
|
+
methods_contents_list.push(data)
|
123
|
+
end
|
124
|
+
data_list.push(methods_contents_list) if methods_contents_list.any?
|
125
|
+
|
126
|
+
# 不要データを除外
|
127
|
+
data_list.reject! { |data| data.include?('def down') }
|
128
|
+
data_list.map { |data| data.reject { |x| /^def\s.*/.match(x) } }.reject(&:empty?)
|
129
|
+
end
|
130
|
+
|
131
|
+
# 出力
|
132
|
+
#
|
133
|
+
# @params [Array] formatted_list
|
134
|
+
def output(formatted_list)
|
135
|
+
# ディレクトリ作成(なければ)
|
136
|
+
FileUtils.mkdir_p(@options[:output])
|
137
|
+
|
138
|
+
# csv作成
|
139
|
+
CSV.open("#{@options[:output]}table_definition.csv", 'w') do |csv|
|
140
|
+
formatted_list.each do |formatted_table|
|
141
|
+
formatted_table.each do |formatted_row|
|
142
|
+
csv << formatted_row
|
143
|
+
end
|
144
|
+
csv << []
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
# カラム整形
|
2
|
+
module NickerPocker
|
3
|
+
module Format
|
4
|
+
class Detail
|
5
|
+
# フォーマット後の各データ格納列
|
6
|
+
COL_PK = 0
|
7
|
+
COL_FK = 1
|
8
|
+
COL_INDEX = 2
|
9
|
+
COL_UNIQUE = 3
|
10
|
+
COL_TYPE = 4
|
11
|
+
COL_COLUMN = 5
|
12
|
+
COL_NULL = 7
|
13
|
+
COL_LIMIT = 8
|
14
|
+
COL_DEFAULT = 9
|
15
|
+
COL_COMMENT = 10
|
16
|
+
COL_MEMO = 12
|
17
|
+
|
18
|
+
# フォーマット後のカラムデータの先頭行
|
19
|
+
ROW_COLUMN_START = 3
|
20
|
+
|
21
|
+
# 各データの格納位置
|
22
|
+
INDEX_COLUMN = 0
|
23
|
+
INDEX_TYPE = 1
|
24
|
+
INDEX_OPTIONS_START = 2
|
25
|
+
|
26
|
+
# add_column用
|
27
|
+
#
|
28
|
+
# @params [Array] method_data_list
|
29
|
+
# @params [Array] table_list
|
30
|
+
# @return [Array]
|
31
|
+
def add_column(method_data_list, table_list)
|
32
|
+
add_list = column_migrate_list(method_data_list)
|
33
|
+
index = table_list.index(table_list.last)
|
34
|
+
|
35
|
+
counter = 0
|
36
|
+
add_list.map do |additions|
|
37
|
+
counter += 1
|
38
|
+
add_row = %W(
|
39
|
+
#{nil} #{nil} #{nil} #{nil}
|
40
|
+
#{additions[:type]} #{additions[:column]} #{nil} #{additions[:null]}
|
41
|
+
#{additions[:limit]} #{additions[:default]} #{additions[:comment]}
|
42
|
+
)
|
43
|
+
|
44
|
+
{ (index + counter) => add_row }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# change_column用
|
49
|
+
#
|
50
|
+
# @params [Array] method_data_list
|
51
|
+
# @params [Array] table_list
|
52
|
+
# @return [Array]
|
53
|
+
def change_column(method_data_list, table_list)
|
54
|
+
change_list = column_migrate_list(method_data_list)
|
55
|
+
column_formatted_list = table_list[ROW_COLUMN_START..]
|
56
|
+
|
57
|
+
change_list.map do |changes|
|
58
|
+
change_row = column_formatted_list.find { |row| row[COL_COLUMN] == changes[:column] }
|
59
|
+
target_index = column_formatted_list.index(change_row) + ROW_COLUMN_START
|
60
|
+
change_row[COL_TYPE] = changes[:type]
|
61
|
+
change_row[COL_NULL] = changes[:null] || change_row[COL_NULL]
|
62
|
+
change_row[COL_LIMIT] = changes[:limit] || change_row[COL_LIMIT]
|
63
|
+
change_row[COL_DEFAULT] = changes[:default] || change_row[COL_DEFAULT]
|
64
|
+
change_row[COL_COMMENT] = changes[:comment] || change_row[COL_COMMENT]
|
65
|
+
|
66
|
+
{ target_index => change_row }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# add_index用
|
71
|
+
#
|
72
|
+
# @params [Array] method_data_list
|
73
|
+
# @params [Array] table_list
|
74
|
+
# @return [Array]
|
75
|
+
def add_index(method_data_list, table_list)
|
76
|
+
column_formatted_list = table_list[ROW_COLUMN_START..]
|
77
|
+
change_list = []
|
78
|
+
|
79
|
+
method_data_list.each do |method_data|
|
80
|
+
index_column_list = [method_data.first]
|
81
|
+
option_list = method_data[1..]
|
82
|
+
|
83
|
+
if index_column_list.first.match(/^\[/)
|
84
|
+
index_end = method_data.index { |x| x.match(/\]/) }
|
85
|
+
index_column_list = method_data[..index_end]
|
86
|
+
option_list = method_data[index_end + 1..]
|
87
|
+
end
|
88
|
+
|
89
|
+
index_column_list.each do |index_column|
|
90
|
+
column_formatted_list.each_with_index do |column_formatted_data, index|
|
91
|
+
next unless index_column.include?(column_formatted_data[COL_COLUMN])
|
92
|
+
|
93
|
+
column_formatted_data[COL_INDEX] = '*'
|
94
|
+
|
95
|
+
if option_list.any?
|
96
|
+
if option_list.find { |option| option.match(/^unique/) }&.match(/true/i)
|
97
|
+
column_formatted_data[COL_UNIQUE] = '*'
|
98
|
+
end
|
99
|
+
|
100
|
+
column_formatted_data[COL_MEMO] = option_list.find { |option| option.match(/^name/) }&.gsub(/^name|\s|:|"/, '')
|
101
|
+
end
|
102
|
+
|
103
|
+
change_list.push({ (index + ROW_COLUMN_START) => column_formatted_data })
|
104
|
+
break
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
change_list
|
110
|
+
end
|
111
|
+
|
112
|
+
# remove_column用
|
113
|
+
#
|
114
|
+
# @params [Array] method_data_list
|
115
|
+
# @params [Array] table_list
|
116
|
+
# @return [Array]
|
117
|
+
def remove_column(method_data_list, table_list)
|
118
|
+
remove_column_list = method_data_list.map { |method_data| method_data[INDEX_COLUMN] }
|
119
|
+
column_formatted_list = table_list[ROW_COLUMN_START..]
|
120
|
+
|
121
|
+
column_formatted_list.map.with_index do |column_formatted_data, index|
|
122
|
+
if remove_column_list.include?(column_formatted_data[COL_COLUMN])
|
123
|
+
{ (index + ROW_COLUMN_START) => nil }
|
124
|
+
end
|
125
|
+
end.compact
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def column_migrate_list(method_data_list)
|
131
|
+
method_data_list.map do |method_data|
|
132
|
+
migrates = {}
|
133
|
+
|
134
|
+
migrates[:column] = method_data[INDEX_COLUMN]
|
135
|
+
migrates[:type] = method_data[INDEX_TYPE]
|
136
|
+
|
137
|
+
option_list = method_data[INDEX_OPTIONS_START..]
|
138
|
+
unless option_list
|
139
|
+
migrates
|
140
|
+
next
|
141
|
+
end
|
142
|
+
|
143
|
+
migrates[:null] = option_list.find { |option| option.match(/^null/) }&.match(/true|false/i)
|
144
|
+
migrates[:limit] = option_list.find { |option| option.match(/^limit/) }&.gsub(/[^\d]/, '')
|
145
|
+
migrates[:default] = option_list.find { |option| option.match(/^default/) }&.gsub(/^default:|\s/, '')
|
146
|
+
migrates[:comment] = option_list.find { |option| option.match(/^comment/) }&.gsub(/^comment:|\s/, '')
|
147
|
+
migrates
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# フォーマッタ
|
2
|
+
module NickerPocker
|
3
|
+
module Format
|
4
|
+
class Operator
|
5
|
+
PROTOTYPE_METHODS = %i(
|
6
|
+
rename_table
|
7
|
+
drop_table
|
8
|
+
rename_column
|
9
|
+
create_table
|
10
|
+
).freeze
|
11
|
+
|
12
|
+
DETAIL_METHODS = %i(
|
13
|
+
add_column
|
14
|
+
change_column
|
15
|
+
add_index
|
16
|
+
remove_column
|
17
|
+
).freeze
|
18
|
+
|
19
|
+
class << self
|
20
|
+
def exec(groups, options = {})
|
21
|
+
new(options).run(groups)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# options[:target_format]
|
26
|
+
def initialize(options)
|
27
|
+
@options = options
|
28
|
+
end
|
29
|
+
|
30
|
+
# 実行
|
31
|
+
#
|
32
|
+
# @params [Hash] groups
|
33
|
+
# @return [Array]
|
34
|
+
def run(groups)
|
35
|
+
return [] if groups.length == 0
|
36
|
+
|
37
|
+
# 各関数の処理をする
|
38
|
+
formatted_list(groups)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# 整形した配列を返す
|
44
|
+
#
|
45
|
+
# @params [Hash] groups
|
46
|
+
# @return [Array]
|
47
|
+
def formatted_list(groups)
|
48
|
+
prototype_formatter = Prototype.new
|
49
|
+
|
50
|
+
# 定義書の原型をつくる
|
51
|
+
table_groups = prototype_formatter.format_groups(groups)
|
52
|
+
table_list = prototype_formatter.table_list(table_groups)
|
53
|
+
|
54
|
+
# カラム整形
|
55
|
+
format_column(table_groups, table_list)
|
56
|
+
end
|
57
|
+
|
58
|
+
# 整形したカラムを返す
|
59
|
+
#
|
60
|
+
# @params [Hash] table_groups
|
61
|
+
# @params [Array] table_list
|
62
|
+
# @return [Array]
|
63
|
+
def format_column(table_groups, table_list)
|
64
|
+
detail_formatter = Detail.new
|
65
|
+
|
66
|
+
table_groups.map do |table_data|
|
67
|
+
target_table_list = table_list.find { |table| table[1].first == table_data.first }
|
68
|
+
|
69
|
+
DETAIL_METHODS.each do |method_name|
|
70
|
+
method_data = table_data[1][method_name]
|
71
|
+
next unless method_data
|
72
|
+
|
73
|
+
change_content_list =
|
74
|
+
detail_formatter.send(method_name, method_data, target_table_list)
|
75
|
+
|
76
|
+
change_content_list.each do |change_contents|
|
77
|
+
index = change_contents.keys.first
|
78
|
+
value = change_contents.values.first
|
79
|
+
|
80
|
+
target_table_list[index] = value
|
81
|
+
end
|
82
|
+
end
|
83
|
+
target_table_list.compact
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
# 定義書の原型をつくる
|
2
|
+
module NickerPocker
|
3
|
+
module Format
|
4
|
+
class Prototype
|
5
|
+
TABLE_HEADER_LIST = %W(
|
6
|
+
table_name
|
7
|
+
#{nil}
|
8
|
+
#{nil}
|
9
|
+
table_name(jp)
|
10
|
+
#{nil}
|
11
|
+
#{nil}
|
12
|
+
created_by
|
13
|
+
created_date
|
14
|
+
updated_by
|
15
|
+
updated_date
|
16
|
+
table_memo
|
17
|
+
).freeze
|
18
|
+
|
19
|
+
COLMN_HEADER_LIST = %W(
|
20
|
+
PK
|
21
|
+
FK
|
22
|
+
index
|
23
|
+
unique
|
24
|
+
type
|
25
|
+
column_name
|
26
|
+
#{nil}
|
27
|
+
null
|
28
|
+
limit
|
29
|
+
default
|
30
|
+
column_name(jp)
|
31
|
+
#{nil}
|
32
|
+
column_memo
|
33
|
+
).freeze
|
34
|
+
|
35
|
+
# グループ整形
|
36
|
+
#
|
37
|
+
# @params [Hash] groups
|
38
|
+
# @return [Hash]
|
39
|
+
def format_groups(groups)
|
40
|
+
return [] if groups.length == 0
|
41
|
+
|
42
|
+
# リネームテーブル処理
|
43
|
+
renamed_groups = rename_table(groups)
|
44
|
+
|
45
|
+
# テーブル削除処理
|
46
|
+
dropped_groups = drop_table(renamed_groups)
|
47
|
+
|
48
|
+
# リネームカラム処理
|
49
|
+
rename_column(dropped_groups)
|
50
|
+
end
|
51
|
+
|
52
|
+
# テーブル作成用配列
|
53
|
+
#
|
54
|
+
# @params [Hash] groups
|
55
|
+
# @return [Hash]
|
56
|
+
def table_list(table_groups)
|
57
|
+
table_groups.map { |table_data| create_table_format(table_data) }
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
# テーブルリネーム処理
|
63
|
+
#
|
64
|
+
# @params [Hash] groups
|
65
|
+
# @return [Hash]
|
66
|
+
def rename_table(groups)
|
67
|
+
temp_list =
|
68
|
+
groups.map do |table_data|
|
69
|
+
if table_data[1][:rename_table]
|
70
|
+
new_table_name = table_data[1][:rename_table].first.first.to_sym
|
71
|
+
[table_data[0], new_table_name]
|
72
|
+
end
|
73
|
+
end.compact
|
74
|
+
|
75
|
+
temp_list.each do |rename_table|
|
76
|
+
old_val = groups[rename_table[1]]
|
77
|
+
# リネーム後のテーブル名に対するmigrateの有無
|
78
|
+
if old_val
|
79
|
+
groups[rename_table[1]] =
|
80
|
+
old_val.merge(groups.delete(rename_table[0])) { |key, old_v, new_v| old_v + new_v }
|
81
|
+
else
|
82
|
+
groups[rename_table[1]] = groups.delete(rename_table[0])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
groups
|
87
|
+
end
|
88
|
+
|
89
|
+
# テーブル削除処理
|
90
|
+
#
|
91
|
+
# @params [Hash] groups
|
92
|
+
# @return [Hash]
|
93
|
+
def drop_table(groups)
|
94
|
+
# 削除対象tableリスト
|
95
|
+
drop_table_list = []
|
96
|
+
groups.each do |table_data|
|
97
|
+
next unless table_data[1][:drop_table]
|
98
|
+
drop_table_list.push(table_data[0])
|
99
|
+
end
|
100
|
+
|
101
|
+
return groups if drop_table_list.empty?
|
102
|
+
|
103
|
+
drop_table_list.each do |drop_table_name|
|
104
|
+
groups.delete(drop_table_name)
|
105
|
+
end
|
106
|
+
|
107
|
+
groups
|
108
|
+
end
|
109
|
+
|
110
|
+
# rename_column用
|
111
|
+
#
|
112
|
+
# @params [Hash] table_groups
|
113
|
+
# @return [Hash]
|
114
|
+
def rename_column(table_groups)
|
115
|
+
rename_target_list = rename_target_list(table_groups)
|
116
|
+
return table_groups if rename_target_list.empty?
|
117
|
+
|
118
|
+
rename_target_list.each do |rename_target|
|
119
|
+
table_name = rename_target.keys.first
|
120
|
+
rename_val_list = rename_target.values.first
|
121
|
+
|
122
|
+
rename_targets = table_groups.delete(table_name)
|
123
|
+
|
124
|
+
key_arr = rename_targets.keys
|
125
|
+
values_arr = rename_targets.values
|
126
|
+
|
127
|
+
rename_val_list.each do |rename_val|
|
128
|
+
old_name = rename_val[0]
|
129
|
+
|
130
|
+
new_name = rename_val[1]
|
131
|
+
values_arr = values_arr.map do |val_arr|
|
132
|
+
val_arr.map { |val|
|
133
|
+
val.map { |v|
|
134
|
+
if /^#{old_name}$/.match?(v)
|
135
|
+
next v.gsub(/^#{old_name}$/, new_name)
|
136
|
+
end
|
137
|
+
v.gsub(/:#{old_name}$/, ":#{new_name}")
|
138
|
+
}
|
139
|
+
}
|
140
|
+
end
|
141
|
+
end
|
142
|
+
table_datas = {}
|
143
|
+
renamed_targets = [key_arr, values_arr].transpose.to_h
|
144
|
+
table_datas[table_name] = renamed_targets
|
145
|
+
table_groups.update(table_datas)
|
146
|
+
end
|
147
|
+
|
148
|
+
table_groups
|
149
|
+
end
|
150
|
+
|
151
|
+
# リネーム対象を返す
|
152
|
+
#
|
153
|
+
# @params [Hash]
|
154
|
+
# @return [Array]
|
155
|
+
def rename_target_list(table_groups)
|
156
|
+
table_groups.map do |table_group|
|
157
|
+
rename_list = table_group[1][:rename_column]
|
158
|
+
next unless rename_list
|
159
|
+
|
160
|
+
{ table_group[0] => rename_list }
|
161
|
+
end.compact
|
162
|
+
end
|
163
|
+
|
164
|
+
# テーブル作成用に整形した配列を返す
|
165
|
+
#
|
166
|
+
# @params [Array] table_data
|
167
|
+
# @return [Array]
|
168
|
+
def create_table_format(table_data)
|
169
|
+
formatted_table_list = []
|
170
|
+
|
171
|
+
# テーブル情報
|
172
|
+
formatted_table_list.push(TABLE_HEADER_LIST)
|
173
|
+
formatted_table_list.push([table_data[0]])
|
174
|
+
|
175
|
+
# カラムヘッダー追加
|
176
|
+
formatted_table_list.push(COLMN_HEADER_LIST)
|
177
|
+
|
178
|
+
methods = table_data[1]
|
179
|
+
columns_list = methods[:create_table].join.split(/t\./).reject(&:empty?)
|
180
|
+
formatted_column_list = create_table(columns_list)
|
181
|
+
|
182
|
+
formatted_table_list.push(*formatted_column_list)
|
183
|
+
end
|
184
|
+
|
185
|
+
# テーブル作成処理
|
186
|
+
#
|
187
|
+
# @params [Array] columns_list
|
188
|
+
# @return [Array]
|
189
|
+
def create_table(columns_list)
|
190
|
+
result_list = []
|
191
|
+
|
192
|
+
# Pキー追加
|
193
|
+
result_list.push(%W(* #{nil} #{nil} #{nil} integer id #{nil} false #{nil} #{nil} ID))
|
194
|
+
|
195
|
+
columns_list.each do |column|
|
196
|
+
column_data_list = column.split(/\s|,|=>/)
|
197
|
+
column_data_list.delete('')
|
198
|
+
|
199
|
+
type = column_data_list[0]
|
200
|
+
|
201
|
+
if type == 'timestamps'
|
202
|
+
timestamps_list = timestamps(column_data_list[1..])
|
203
|
+
result_list.push(*timestamps_list)
|
204
|
+
next
|
205
|
+
end
|
206
|
+
|
207
|
+
name = column_data_list[1]&.sub(/^:/, '')
|
208
|
+
null, limit, default, comment = constraints(column_data_list[2..])
|
209
|
+
|
210
|
+
result_list.push(%W(#{nil} #{nil} #{nil} #{nil} #{type} #{name} #{nil} #{null} #{limit} #{default} #{comment}))
|
211
|
+
end
|
212
|
+
|
213
|
+
result_list
|
214
|
+
end
|
215
|
+
|
216
|
+
# 作成・更新日時カラム追加処理
|
217
|
+
#
|
218
|
+
# @params [Array] timestamps_left_list
|
219
|
+
# @return [Array]
|
220
|
+
def timestamps(timestamps_left_list)
|
221
|
+
timestamps_list = []
|
222
|
+
|
223
|
+
null, limit, default, comment = constraints(timestamps_left_list)
|
224
|
+
|
225
|
+
timestamps_list.push(%W(#{nil} #{nil} #{nil} #{nil} timestamp created_at #{nil} #{null} #{limit} #{default} #{comment}))
|
226
|
+
timestamps_list.push(%W(#{nil} #{nil} #{nil} #{nil} timestamp updated_at #{nil} #{null} #{limit} #{default} #{comment}))
|
227
|
+
end
|
228
|
+
|
229
|
+
# 各制約
|
230
|
+
#
|
231
|
+
# @params [Array] left_list
|
232
|
+
def constraints(left_list)
|
233
|
+
return if left_list.nil? || left_list.empty?
|
234
|
+
|
235
|
+
temp_constraint_list = left_list.map { |column_data| column_data.gsub(/:|'/, '') }
|
236
|
+
constraints = temp_constraint_list.each_slice(2).to_h
|
237
|
+
|
238
|
+
%W(#{constraints['null']} #{constraints['limit']} #{constraints['default']} #{constraints['comment']})
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# テーブルごとにグループ化
|
2
|
+
module NickerPocker
|
3
|
+
class Grouping
|
4
|
+
class << self
|
5
|
+
def exec(data_list, options = {})
|
6
|
+
new(options).run(data_list)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# options[:target_tables]
|
11
|
+
# options[:target_files]
|
12
|
+
def initialize(options)
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
# 実行
|
17
|
+
#
|
18
|
+
# @params [Array] data_list
|
19
|
+
# @return [Hash]
|
20
|
+
def run(data_list)
|
21
|
+
return {} if data_list.length == 0
|
22
|
+
|
23
|
+
# テーブルごとにまとめる
|
24
|
+
grouping(data_list)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
# テーブルごと・メソッドごとにグルーピング
|
30
|
+
#
|
31
|
+
# @params [Array] data_list
|
32
|
+
# @return [Hash]
|
33
|
+
def grouping(data_list)
|
34
|
+
temp_group_list = data_list.map { |data| data.map { |row| format_raw_data(row) } }.flatten
|
35
|
+
|
36
|
+
groups = {}
|
37
|
+
temp_group_list.each do |temp_group|
|
38
|
+
table_name = temp_group.first.first
|
39
|
+
methods = temp_group.first[1]
|
40
|
+
method_name = methods.keys.first
|
41
|
+
|
42
|
+
groups[table_name] = {} unless groups[table_name]
|
43
|
+
groups[table_name][method_name] = [] unless groups[table_name][method_name]
|
44
|
+
|
45
|
+
groups[table_name][method_name].push(methods.values.first)
|
46
|
+
end
|
47
|
+
|
48
|
+
# 出力対象を絞る
|
49
|
+
groups.each { |group| group.delete(group[0]) }
|
50
|
+
groups
|
51
|
+
end
|
52
|
+
|
53
|
+
# データを整形
|
54
|
+
def format_raw_data(data)
|
55
|
+
# メソッド・対象テーブルを取得
|
56
|
+
tables = {}
|
57
|
+
methods = {}
|
58
|
+
|
59
|
+
target_method = target_method(data.first).to_sym
|
60
|
+
return unless target_method
|
61
|
+
|
62
|
+
method_row = data.first.split(/,/)
|
63
|
+
table_name = method_row[0].split(/\s/)[1].sub(/^:/, '').to_sym
|
64
|
+
|
65
|
+
method_contents = data.length > 1 ? data[1..] : method_row[1..]
|
66
|
+
method_contents = method_contents.map { |content| content.strip.sub(/^:/, '') }.reject(&:empty?)
|
67
|
+
|
68
|
+
methods[target_method] = method_contents
|
69
|
+
|
70
|
+
tables[table_name] = methods
|
71
|
+
tables
|
72
|
+
end
|
73
|
+
|
74
|
+
def target_method(str)
|
75
|
+
MIGRATE_METHODS.each do |method_name|
|
76
|
+
return method_name if /#{method_name.to_s}/.match(str)
|
77
|
+
end
|
78
|
+
|
79
|
+
return
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/nicker_pocker.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative
|
2
|
+
require_relative 'nicker_pocker/format/operator'
|
3
|
+
require_relative 'nicker_pocker/format/prototype'
|
4
|
+
require_relative 'nicker_pocker/format/detail'
|
5
|
+
require_relative 'nicker_pocker/command'
|
6
|
+
require_relative 'nicker_pocker/grouping'
|
4
7
|
|
5
8
|
module NickerPocker
|
6
9
|
class Error < StandardError; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nicker_pocker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ms919
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-06-10 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -21,10 +21,16 @@ files:
|
|
21
21
|
- ".rubocop.yml"
|
22
22
|
- CHANGELOG.md
|
23
23
|
- Gemfile
|
24
|
+
- Gemfile.lock
|
24
25
|
- LICENSE.txt
|
25
26
|
- README.md
|
26
27
|
- Rakefile
|
27
28
|
- lib/nicker_pocker.rb
|
29
|
+
- lib/nicker_pocker/command.rb
|
30
|
+
- lib/nicker_pocker/format/detail.rb
|
31
|
+
- lib/nicker_pocker/format/operator.rb
|
32
|
+
- lib/nicker_pocker/format/prototype.rb
|
33
|
+
- lib/nicker_pocker/grouping.rb
|
28
34
|
- lib/nicker_pocker/version.rb
|
29
35
|
- nicker_pocker.gemspec
|
30
36
|
- sig/nicker_pocker.rbs
|