pry-helper 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.solargraph.yml +11 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +75 -0
- data/LICENSE.txt +21 -0
- data/README.md +8 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/pry-helper/commands/models.rb +44 -0
- data/lib/pry-helper/commands/table.rb +55 -0
- data/lib/pry-helper/commands/vd.rb +46 -0
- data/lib/pry-helper/commands.rb +6 -0
- data/lib/pry-helper/concerns/global_data_definition.rb +245 -0
- data/lib/pry-helper/concerns/table_data_definition.rb +550 -0
- data/lib/pry-helper/concerns.rb +2 -0
- data/lib/pry-helper/definition.rb +246 -0
- data/lib/pry-helper/ext/active_record/connection_adapters/abstract_mysql_adapter.rb +53 -0
- data/lib/pry-helper/ext/active_record/connection_adapters/postgresql/schema_statements.rb +8 -0
- data/lib/pry-helper/ext/array.rb +168 -0
- data/lib/pry-helper/ext/hash.rb +41 -0
- data/lib/pry-helper/ext/kernel.rb +111 -0
- data/lib/pry-helper/ext/object.rb +22 -0
- data/lib/pry-helper/ext/string.rb +13 -0
- data/lib/pry-helper/ext/time.rb +15 -0
- data/lib/pry-helper/ext.rb +5 -0
- data/lib/pry-helper/id.rb +59 -0
- data/lib/pry-helper/mysqldump.rb +44 -0
- data/lib/pry-helper/vd.rb +42 -0
- data/lib/pry-helper/version.rb +3 -0
- data/lib/pry-helper.rb +20 -0
- data/pry-helper.gemspec +32 -0
- metadata +188 -0
@@ -0,0 +1,246 @@
|
|
1
|
+
require 'pry-helper/concerns'
|
2
|
+
require 'pry-helper/vd'
|
3
|
+
|
4
|
+
module PryHelper
|
5
|
+
module Extension
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
def t
|
9
|
+
puts Terminal::Table.new { |t|
|
10
|
+
v.each { |row| t << (row || :separator) }
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
def vd
|
15
|
+
VD.new do |vd|
|
16
|
+
vd << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
|
17
|
+
self.class.connection.columns(self.class.table_name).each do |column|
|
18
|
+
vd << [column.name, read_attribute(column.name), column.sql_type, column.comment || '']
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def v
|
24
|
+
t = []
|
25
|
+
t << ['Attribute Name', 'Attribute Value', 'SQL Type', 'Comment']
|
26
|
+
t << nil
|
27
|
+
self.class.connection.columns(self.class.table_name).each do |column|
|
28
|
+
t << [column.name, read_attribute(column.name), column.sql_type, column.comment || '']
|
29
|
+
end
|
30
|
+
t
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_insert_sql
|
34
|
+
self.class.to_insert_sql([self])
|
35
|
+
end
|
36
|
+
|
37
|
+
def to_upsert_sql
|
38
|
+
self.class.to_upsert_sql([self])
|
39
|
+
end
|
40
|
+
|
41
|
+
def write_csv(filename, *fields, **options)
|
42
|
+
[self].write_csv(filename, *fields, **options)
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_excel(filename, *fields, **options)
|
46
|
+
[self].write_excel(filename, *fields, **options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def dump(filename, batch_size=500)
|
50
|
+
[self].dump(filename, batch_size)
|
51
|
+
end
|
52
|
+
|
53
|
+
included do
|
54
|
+
end
|
55
|
+
|
56
|
+
class_methods do
|
57
|
+
def t
|
58
|
+
table_name = Commands::Table::get_table_name(name)
|
59
|
+
puts "\nTable: #{table_name}"
|
60
|
+
puts Commands::Table::table_info_table(table_name)
|
61
|
+
end
|
62
|
+
|
63
|
+
def vd
|
64
|
+
table_name = Commands::Table::get_table_name(name)
|
65
|
+
Commands::VD::table_info_vd(table_name)
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
|
69
|
+
def v
|
70
|
+
table_name = Commands::Table::get_table_name(name)
|
71
|
+
Commands::Table::table_info(table_name)
|
72
|
+
end
|
73
|
+
def to_insert_sql(records, batch_size=1)
|
74
|
+
to_sql(records, :skip, batch_size)
|
75
|
+
end
|
76
|
+
|
77
|
+
def to_upsert_sql(records, batch_size=1)
|
78
|
+
to_sql(records, :update, batch_size)
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_sql(records, on_duplicate, batch_size)
|
82
|
+
records.in_groups_of(batch_size, false).map do |group|
|
83
|
+
ActiveRecord::InsertAll.new(self, group.map(&:attributes), on_duplicate: on_duplicate).send(:to_sql) + ';'
|
84
|
+
end.join("\n")
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_create_sql
|
88
|
+
ActiveRecord::Base.connection.exec_query("show create table #{table_name}").rows.last.last
|
89
|
+
end
|
90
|
+
|
91
|
+
def dump(filename, no_create_table=false)
|
92
|
+
PryHelper::Mysqldump.new.dump_table(filename, table_name, no_create_table)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class Definition
|
98
|
+
class << self
|
99
|
+
def models
|
100
|
+
@@models ||= []
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def initialize
|
105
|
+
@@models = []
|
106
|
+
|
107
|
+
ActiveRecord::Base.connection.tap do |conn|
|
108
|
+
defined_models = ::ApplicationRecord.descendants
|
109
|
+
tables = conn.tables
|
110
|
+
if conn.adapter_name == 'Mysql2'
|
111
|
+
conn.define_singleton_method(:dump) do |filename, no_create_db=false|
|
112
|
+
PryHelper::Mysqldump.new.dump_database(filename, no_create_db)
|
113
|
+
end
|
114
|
+
require 'pry-helper/ext/active_record/connection_adapters/abstract_mysql_adapter'
|
115
|
+
comments = conn.table_comment_of_tables(tables)
|
116
|
+
primary_keys = conn.primary_keys_of_tables(tables)
|
117
|
+
else
|
118
|
+
comments = tables.map { |t| [t, conn.table_comment(t)] }.to_h
|
119
|
+
primary_keys = tables.map { |t| [t, conn.primary_keys(t)] }.to_h
|
120
|
+
end
|
121
|
+
|
122
|
+
ApplicationRecord.include(PryHelper::Extension)
|
123
|
+
|
124
|
+
tables.each do |table_name|
|
125
|
+
table_comment = comments[table_name]
|
126
|
+
primary_keys[table_name].tap do |pkey|
|
127
|
+
table_name.camelize.tap do |const_name|
|
128
|
+
const_name = 'Modul' if const_name == 'Module'
|
129
|
+
const_name = 'Clazz' if const_name == 'Class'
|
130
|
+
if model_class = defined_models.find { |m| m.table_name == table_name }
|
131
|
+
model_class.tap do |clazz|
|
132
|
+
model_class.name.gsub(/[a-z]*/, '').tap do |bare_abbr|
|
133
|
+
abbr_const = nil
|
134
|
+
9.times do |idx|
|
135
|
+
abbr = idx.zero? ? bare_abbr : "#{bare_abbr}#{idx+1}"
|
136
|
+
unless Object.const_defined?(abbr)
|
137
|
+
Object.const_set abbr, model_class
|
138
|
+
abbr_const = abbr
|
139
|
+
break
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
@@models << {
|
144
|
+
model: model_class,
|
145
|
+
abbr: abbr_const,
|
146
|
+
table: table_name,
|
147
|
+
comment: table_comment
|
148
|
+
}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
else
|
152
|
+
Class.new(::ApplicationRecord) do
|
153
|
+
if pkey.is_a?(Array) && pkey.size > 1
|
154
|
+
self.primary_keys = pkey
|
155
|
+
else
|
156
|
+
self.primary_key = pkey&.first
|
157
|
+
end
|
158
|
+
self.table_name = table_name
|
159
|
+
self.inheritance_column = nil
|
160
|
+
ActiveRecord.default_timezone = :local
|
161
|
+
end.tap do |clazz|
|
162
|
+
Object.const_set(const_name, clazz).tap do |const|
|
163
|
+
const_name.gsub(/[a-z]*/, '').tap do |bare_abbr|
|
164
|
+
abbr_const = nil
|
165
|
+
9.times do |idx|
|
166
|
+
abbr = idx.zero? ? bare_abbr : "#{bare_abbr}#{idx+1}"
|
167
|
+
unless Object.const_defined?(abbr)
|
168
|
+
Object.const_set abbr, const
|
169
|
+
abbr_const = abbr
|
170
|
+
break
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
@@models << {
|
175
|
+
model: const,
|
176
|
+
abbr: abbr_const,
|
177
|
+
table: table_name,
|
178
|
+
comment: table_comment
|
179
|
+
}
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
::ActiveRecord::Relation.class_eval do
|
191
|
+
def t(*attrs, **options)
|
192
|
+
records.t(*attrs, **options)
|
193
|
+
end
|
194
|
+
|
195
|
+
def vd(*attrs, **options)
|
196
|
+
records.vd(*attrs, **options)
|
197
|
+
end
|
198
|
+
|
199
|
+
def v
|
200
|
+
records.v
|
201
|
+
end
|
202
|
+
|
203
|
+
def a
|
204
|
+
to_a
|
205
|
+
end
|
206
|
+
|
207
|
+
def write_csv(filename, *fields, **options)
|
208
|
+
records.write_csv(filename, *fields, **options)
|
209
|
+
end
|
210
|
+
|
211
|
+
def write_excel(filename, *fields, **options)
|
212
|
+
records.write_excel(filename, *fields, **options)
|
213
|
+
end
|
214
|
+
|
215
|
+
def dump(filename, batch_size=500)
|
216
|
+
records.dump(filename, batch_size)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
::ActiveRecord::Result.class_eval do
|
221
|
+
def t(*attrs, **options)
|
222
|
+
to_a.t(*attrs, **options)
|
223
|
+
end
|
224
|
+
|
225
|
+
def vd(*attrs, **options)
|
226
|
+
to_a.vd(*attrs, **options)
|
227
|
+
end
|
228
|
+
|
229
|
+
def v
|
230
|
+
to_a.v
|
231
|
+
end
|
232
|
+
|
233
|
+
def a
|
234
|
+
to_a
|
235
|
+
end
|
236
|
+
|
237
|
+
def write_csv(filename, *fields, **options)
|
238
|
+
to_a.write_csv(filename, *fields, **options)
|
239
|
+
end
|
240
|
+
|
241
|
+
def write_excel(filename, *fields, **options)
|
242
|
+
to_a.write_excel(filename, *fields, **options)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'active_record/connection_adapters/abstract_mysql_adapter'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
class AbstractMysqlAdapter
|
6
|
+
|
7
|
+
def extract_schema_qualified_name_of_tables(table_names)
|
8
|
+
table_names.map do |string|
|
9
|
+
schema, name = string.to_s.scan(/[^`.\s]+|`[^`]*`/)
|
10
|
+
schema, name = nil, schema unless name
|
11
|
+
[schema, name]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def quoted_scope_of_tables(names = nil)
|
16
|
+
extract_schema_qualified_name_of_tables(names).map do |(schema, name)|
|
17
|
+
scope = {}
|
18
|
+
scope[:schema] = schema ? quote(schema) : "database()"
|
19
|
+
scope[:name] = quote(name) if name
|
20
|
+
scope
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def primary_keys_of_tables(table_names) # :nodoc:
|
25
|
+
raise ArgumentError unless table_names.present?
|
26
|
+
|
27
|
+
scopes = quoted_scope_of_tables(table_names)
|
28
|
+
|
29
|
+
res = query(<<~SQL, "SCHEMA")
|
30
|
+
SELECT table_name, column_name
|
31
|
+
FROM information_schema.statistics
|
32
|
+
WHERE index_name = 'PRIMARY'
|
33
|
+
AND (table_schema, table_name) in
|
34
|
+
(#{scopes.map { |scope| "(#{scope[:schema]}, #{scope[:name]})" }.join(', ')})
|
35
|
+
ORDER BY seq_in_index
|
36
|
+
SQL
|
37
|
+
|
38
|
+
res.group_by(&:first).map { |table, vlaues| [table, vlaues.map(&:last)] }.to_h
|
39
|
+
end
|
40
|
+
|
41
|
+
def table_comment_of_tables(table_names) # :nodoc:
|
42
|
+
scopes = quoted_scope_of_tables(table_names)
|
43
|
+
|
44
|
+
query(<<~SQL, "SCHEMA").presence.try(&:to_h)
|
45
|
+
SELECT table_name, table_comment
|
46
|
+
FROM information_schema.tables
|
47
|
+
WHERE (table_schema, table_name) in
|
48
|
+
(#{scopes.map { |scope| "(#{scope[:schema]}, #{scope[:name]})" }.join(', ')})
|
49
|
+
SQL
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'pry-helper/vd'
|
2
|
+
|
3
|
+
class Array
|
4
|
+
def to_insert_sql(batch_size=500)
|
5
|
+
raise 'All element should be an ActiveRecord instance object' unless all? { |e| e.is_a?(ActiveRecord::Base) }
|
6
|
+
group_by(&:class).map do |(klass, records)|
|
7
|
+
klass.to_insert_sql(records, batch_size)
|
8
|
+
end.join("\n")
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_upsert_sql(batch_size=500)
|
12
|
+
raise 'All element should be an ActiveRecord instance object' unless all? { |e| e.is_a?(ActiveRecord::Base) }
|
13
|
+
group_by(&:class).map do |(klass, records)|
|
14
|
+
klass.to_upsert_sql(records, batch_size)
|
15
|
+
end.join("\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
def t(*attrs, **options)
|
19
|
+
if (attrs.present? || options.present? && options[:except]) && present? && first.is_a?(ActiveRecord::Base)
|
20
|
+
column_names = first.attribute_names.map(&:to_sym)
|
21
|
+
attrs = attrs.flat_map { |e| e.is_a?(Regexp) ? column_names.grep(e) : e }.uniq
|
22
|
+
if options.present? && options[:except]
|
23
|
+
attrs = column_names if attrs.empty?
|
24
|
+
if options[:except].is_a?(Regexp)
|
25
|
+
attrs.reject! { |e| e =~ options[:except] }
|
26
|
+
else
|
27
|
+
attrs -= [options[:except]].flatten
|
28
|
+
end
|
29
|
+
end
|
30
|
+
puts Terminal::Table.new { |t|
|
31
|
+
t << attrs
|
32
|
+
t << :separator
|
33
|
+
each do |e|
|
34
|
+
t << e.attributes.values_at(*attrs.map(&:to_s))
|
35
|
+
end
|
36
|
+
}
|
37
|
+
else
|
38
|
+
table = Terminal::Table.new { |t|
|
39
|
+
v.each { |row| t << (row || :separator)}
|
40
|
+
}.to_s
|
41
|
+
|
42
|
+
terminal_width = `tput cols`.to_i
|
43
|
+
if table.lines.first.size > terminal_width
|
44
|
+
table = table.lines.map(&:chomp)
|
45
|
+
puts table[0..2].join("\n")
|
46
|
+
puts table[3..-1].join("\n#{'-' * terminal_width}\n")
|
47
|
+
else
|
48
|
+
puts table
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def vd(*attrs, **options)
|
54
|
+
if (attrs.present? || options.present? && options[:except]) && present? && first.is_a?(ActiveRecord::Base)
|
55
|
+
column_names = first.attribute_names.map(&:to_sym)
|
56
|
+
attrs = attrs.flat_map { |e| e.is_a?(Regexp) ? column_names.grep(e) : e }.uniq
|
57
|
+
if options.present? && options[:except]
|
58
|
+
attrs = column_names if attrs.empty?
|
59
|
+
if options[:except].is_a?(Regexp)
|
60
|
+
attrs.reject! { |e| e =~ options[:except] }
|
61
|
+
else
|
62
|
+
attrs -= [options[:except]].flatten
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
PryHelper::VD.new do |vd|
|
67
|
+
vd << attrs
|
68
|
+
each do |e|
|
69
|
+
vd << e.attributes.values_at(*attrs.map(&:to_s))
|
70
|
+
end
|
71
|
+
end
|
72
|
+
else
|
73
|
+
PryHelper::VD.new do |vd|
|
74
|
+
v.each { |row| vd << row if row }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def v
|
81
|
+
return self unless present?
|
82
|
+
t = []
|
83
|
+
if map(&:class).uniq.size == 1
|
84
|
+
if first.is_a?(ActiveRecord::Base)
|
85
|
+
t << first.attribute_names
|
86
|
+
t << nil
|
87
|
+
each do |e|
|
88
|
+
t << e.attributes.values_at(*first.attribute_names).map(&:as_json)
|
89
|
+
end
|
90
|
+
elsif first.is_a?(Array)
|
91
|
+
t = map { |a| a.map(&:as_json) }
|
92
|
+
elsif first.is_a?(Hash) || first.is_a?(ActiveSupport::HashWithIndifferentAccess)
|
93
|
+
t << first.keys
|
94
|
+
t << nil
|
95
|
+
each do |e|
|
96
|
+
t << e.values_at(*first.keys).map(&:as_json)
|
97
|
+
end
|
98
|
+
else
|
99
|
+
return self
|
100
|
+
end
|
101
|
+
end
|
102
|
+
t
|
103
|
+
end
|
104
|
+
|
105
|
+
def write_csv(filename, *fields, **options)
|
106
|
+
generate_csv(filename, **options) do |csv|
|
107
|
+
if size > 0 && first.is_a?(ActiveRecord::Base)
|
108
|
+
if fields.empty?
|
109
|
+
fields = first.attributes.keys
|
110
|
+
else
|
111
|
+
fields = fields.map(&:to_s)
|
112
|
+
end
|
113
|
+
csv << fields
|
114
|
+
end
|
115
|
+
if size > 0 && first.is_a?(Hash)
|
116
|
+
if fields.empty?
|
117
|
+
fields = first.keys
|
118
|
+
end
|
119
|
+
csv << fields
|
120
|
+
end
|
121
|
+
each do |row|
|
122
|
+
if row.is_a?(Array)
|
123
|
+
csv << row.map(&:to_s)
|
124
|
+
else
|
125
|
+
csv << row.slice(*fields).values.map(&:to_s)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def write_excel(filename, *fields, **options)
|
132
|
+
sheet_name = options[:sheet_name] || 'Sheet1'
|
133
|
+
generate_excel(filename) do |workbook|
|
134
|
+
workbook.add_worksheet(name: sheet_name) do |sheet|
|
135
|
+
if size > 0 && first.is_a?(ActiveRecord::Base)
|
136
|
+
if fields.empty?
|
137
|
+
fields = first.attributes.keys
|
138
|
+
else
|
139
|
+
fields = fields.map(&:to_s)
|
140
|
+
end
|
141
|
+
sheet.add_row(fields, types: [:string] * fields.size)
|
142
|
+
end
|
143
|
+
if size > 0 && first.is_a?(Hash)
|
144
|
+
if fields.empty?
|
145
|
+
fields = first.keys
|
146
|
+
end
|
147
|
+
sheet.add_row(fields, types: [:string] * fields.size)
|
148
|
+
end
|
149
|
+
each do |row|
|
150
|
+
if row.is_a?(Array)
|
151
|
+
sheet.add_row(row.map(&:to_s), types: [:string] * row.size)
|
152
|
+
else
|
153
|
+
sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def dump(filename, batch_size=500)
|
161
|
+
File.open(File.expand_path(filename), 'w') do |file|
|
162
|
+
group_by(&:class).each do |(klass, records)|
|
163
|
+
file.puts(klass.to_upsert_sql(records, batch_size))
|
164
|
+
end
|
165
|
+
end
|
166
|
+
{size: size, file: File.expand_path(filename)}
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Hash
|
2
|
+
def write_excel(filename)
|
3
|
+
generate_excel(filename) do |workbook|
|
4
|
+
each do |sheet_name, sheet_data|
|
5
|
+
workbook.add_worksheet(name: sheet_name) do |sheet|
|
6
|
+
if sheet_data.is_a?(Hash)
|
7
|
+
fields = sheet_data[:fields].map(&:to_s)
|
8
|
+
sheet.add_row(fields, types: [:string] * fields.size)
|
9
|
+
sheet_data[:data].each do |row|
|
10
|
+
sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
if sheet_data.is_a?(Array)
|
15
|
+
if sheet_data.size > 0 && sheet_data.first.is_a?(ActiveModel::Base)
|
16
|
+
fields = sheet_data.first.attributes.keys
|
17
|
+
sheet.add_row(fields, types: [:string] * fields.size)
|
18
|
+
sheet_data.each do |row|
|
19
|
+
sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if sheet_data.size > 0 && sheet_data.first.is_a?(Hash)
|
24
|
+
fields = sheet_data.first.keys
|
25
|
+
sheet.add_row(fields, types: [:string] * fields.size)
|
26
|
+
sheet_data.each do |row|
|
27
|
+
sheet.add_row(row.slice(*fields).values.map(&:to_s), types: [:string] * fields.size)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
if sheet_data.size > 0 && sheet_data.first.is_a?(Array)
|
32
|
+
sheet_data.each do |row|
|
33
|
+
sheet.add_row(row.map(&:to_s), types: [:string] * fields.size)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'pry-helper/concerns'
|
2
|
+
module Kernel
|
3
|
+
CSV_BOM = "\xef\xbb\xbf"
|
4
|
+
|
5
|
+
include ::PryHelper::Concerns::GlobalDataDefinition
|
6
|
+
|
7
|
+
def sql(sql)
|
8
|
+
ActiveRecord::Base.connection.exec_query(sql)
|
9
|
+
end
|
10
|
+
|
11
|
+
def print_tables(format = :md)
|
12
|
+
|
13
|
+
tables = ActiveRecord::Base.connection.tables.map do |table_name|
|
14
|
+
{
|
15
|
+
table: table_name,
|
16
|
+
table_comment: ActiveRecord::Base.connection.table_comment(table_name) || '',
|
17
|
+
columns: ::ActiveRecord::Base.connection.columns(table_name)
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
outputs = tables.map do |table|
|
22
|
+
table_name = table[:table]
|
23
|
+
table_comment = table[:table_comment]
|
24
|
+
case format
|
25
|
+
when :md
|
26
|
+
"# #{table_name} #{table_comment}\n\n" +
|
27
|
+
Terminal::Table.new { |t|
|
28
|
+
t.headings = ['PK', 'Name', 'SQL Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
|
29
|
+
t.rows = table[:columns].map { |column|
|
30
|
+
pk = if [::ActiveRecord::Base.connection.primary_key(table_name)].flatten.include?(column)
|
31
|
+
'Y'
|
32
|
+
else
|
33
|
+
''
|
34
|
+
end
|
35
|
+
[pk, "`#{column.name}`", column.sql_type, column.sql_type_metadata.limit || '', column.sql_type_metadata.precision || '',
|
36
|
+
column.sql_type_metadata.scale || '', column.default || '', column.null, column.comment || '']
|
37
|
+
}
|
38
|
+
t.style = {
|
39
|
+
border_top: false,
|
40
|
+
border_bottom: false,
|
41
|
+
border_i: '|'
|
42
|
+
}
|
43
|
+
}.to_s.lines.map { |l| ' ' + l }.join
|
44
|
+
when :org
|
45
|
+
"* #{table_name} #{table_comment}\n\n" +
|
46
|
+
Terminal::Table.new { |t|
|
47
|
+
t.headings = ['PK', 'Name', 'SQL Type', 'Limit', 'Precision', 'Scale', 'Default', 'Nullable', 'Comment']
|
48
|
+
t.rows = table[:columns].map { |column|
|
49
|
+
pk = if [::ActiveRecord::Base.connection.primary_key(table_name)].flatten.include?(column)
|
50
|
+
'Y'
|
51
|
+
else
|
52
|
+
''
|
53
|
+
end
|
54
|
+
[pk, "=#{column.name}=", column.sql_type, column.sql_type_metadata.limit || '', column.sql_type_metadata.precision || '',
|
55
|
+
column.sql_type_metadata.scale || '', column.default || '', column.null, column.comment || '']
|
56
|
+
}
|
57
|
+
t.style = {
|
58
|
+
border_top: false,
|
59
|
+
border_bottom: false,
|
60
|
+
}
|
61
|
+
}.to_s.lines.map { |l| ' ' + l.gsub(/^\+|\+$/, '|') }.join
|
62
|
+
when :sql
|
63
|
+
"-- Table: #{table_name}\n\n" + ActiveRecord::Base.connection.exec_query("show create table `#{table_name}`").rows.last.last + ';'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
outputs.each { |out| puts out; puts }
|
68
|
+
end
|
69
|
+
|
70
|
+
def generate_csv(filename, **options, &block)
|
71
|
+
opts = {
|
72
|
+
col_sep: "\t",
|
73
|
+
row_sep: "\r\n"
|
74
|
+
}
|
75
|
+
opts.merge!(options.except(:encoding))
|
76
|
+
encoding = options[:encoding] || 'UTF-16LE'
|
77
|
+
File.open(File.expand_path(filename), "w:#{encoding}") do |file|
|
78
|
+
file.write(CSV_BOM)
|
79
|
+
file.write CSV.generate(**opts, &block)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def parse_csv(filename, **options)
|
84
|
+
encoding = options[:encoding] || 'UTF-16'
|
85
|
+
opts = {
|
86
|
+
headers: false,
|
87
|
+
col_sep: "\t",
|
88
|
+
row_sep: "\r\n"
|
89
|
+
}
|
90
|
+
opts.merge!(options.except(:encoding))
|
91
|
+
CSV.parse(IO.read(File.expand_path(filename), encoding: encoding, binmode: true).encode('UTF-8'), **opts).to_a
|
92
|
+
end
|
93
|
+
|
94
|
+
def generate_excel(filename)
|
95
|
+
Axlsx::Package.new do |package|
|
96
|
+
yield(package.workbook)
|
97
|
+
package.serialize(File.expand_path(filename))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def parse_excel(filename)
|
102
|
+
xlsx = Roo::Excelx.new(File.expand_path(filename))
|
103
|
+
xlsx.sheets.each_with_object({}) do |sheet_name, result|
|
104
|
+
begin
|
105
|
+
result[sheet_name] = xlsx.sheet(sheet_name).to_a
|
106
|
+
rescue
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'active_support/core_ext/time/conversions'
|
2
|
+
require 'active_support/core_ext/object/json'
|
3
|
+
|
4
|
+
class Time
|
5
|
+
DATE_FORMATS ||= {}
|
6
|
+
DATE_FORMATS[:default] = '%Y-%m-%d %H:%M:%S'
|
7
|
+
|
8
|
+
def inspect
|
9
|
+
to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
def as_json(*args)
|
13
|
+
to_s
|
14
|
+
end
|
15
|
+
end
|