kandata 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +18 -2
- data/lib/kandata.rb +2 -2
- data/lib/kandata/database.rb +20 -11
- data/lib/kandata/database/connection_info.rb +3 -1
- data/lib/kandata/tsv_file.rb +38 -12
- data/lib/kandata/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9841a7b354143f7fbdd512e7e1c84ee3cfe97622
|
4
|
+
data.tar.gz: 8f4a1bab20ab17cde5580e27ca0376edd6e53d42
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb5391ce2ee2ac7112ce5320ebf7df616bee2d6baad69636c43342b50840148a465670796816713c7f1304bfc1e53170e6300d344852e75554e3ef5c0d086c2f
|
7
|
+
data.tar.gz: 5b29c796225cc9d6cf73b0fc70c77b5efc305c4c6a93ae2787dfe00d6be119b481b4440abf25148f76751e8496e5cef0a24ca210e55fdb276ce3ad4c991094ed
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Kandata
|
2
2
|
|
3
|
-
[![CircleCI](https://circleci.com/gh/
|
3
|
+
[![CircleCI](https://circleci.com/gh/eLicenseSystems/kandata.svg?style=svg)](https://circleci.com/gh/eLicenseSystems/kandata)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/kandata.svg)](https://badge.fury.io/rb/kandata)
|
5
5
|
|
6
6
|
Kandataは、TSVファイルを自分のローカルのMySQLデータベース内に簡単にロードするためのツールです。
|
@@ -16,6 +16,22 @@ MySQLサーバーがローカルで動作している必要があります。
|
|
16
16
|
|
17
17
|
## 利用方法
|
18
18
|
|
19
|
+
### Rubyスクリプト内から利用する場合
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
require 'kandata'
|
23
|
+
|
24
|
+
# TSVからデータ生成
|
25
|
+
# ローカルのMySQLサーバーのKandataデータベース内にuserテーブルを作成して、TSVでデータを流し込む
|
26
|
+
my_user = Kandata.build_from_tsv('./user.tsv')
|
27
|
+
|
28
|
+
# my_user はActiveRecordをextendしたクラスそのものなので、
|
29
|
+
# Railsのモデルクラスのように使って色々出来る。
|
30
|
+
# ex) my_user.where(last_login: nil).each do |v| v.disactivate end
|
31
|
+
```
|
32
|
+
|
33
|
+
### コマンドラインから実行する場合
|
34
|
+
|
19
35
|
以下のように実行します。
|
20
36
|
|
21
37
|
$ kandata load_tsv TSVファイル名 [--force]
|
@@ -37,7 +53,7 @@ MySQLサーバーがローカルで動作している必要があります。
|
|
37
53
|
- 各カラムへのINDEXの追加には対応していません。必要な場合は自分でSQLで`CREATE INDEX`してください。
|
38
54
|
|
39
55
|
## 今後の予定
|
40
|
-
-
|
56
|
+
- ~作成したテーブルに応じたActiveRecordモデルを自動生成できるようにする。~ **done**
|
41
57
|
- `require`で非RailsなRubyスクリプトで読み込んで使えるように。
|
42
58
|
- 作成したテーブルのバックアップなどの機能を追加する。
|
43
59
|
|
data/lib/kandata.rb
CHANGED
@@ -16,8 +16,8 @@ class Kandata
|
|
16
16
|
end
|
17
17
|
|
18
18
|
# テーブルを作成し、テーブルにデータを読み込み、テーブル名を戻す
|
19
|
-
def self.load_tsv(filename, force_load)
|
19
|
+
def self.load_tsv(filename, force_load, headers = nil)
|
20
20
|
client = Kandata::Database.new
|
21
|
-
client.load_tsv(filename, force_load)
|
21
|
+
client.load_tsv(filename, force_load, headers)
|
22
22
|
end
|
23
23
|
end
|
data/lib/kandata/database.rb
CHANGED
@@ -3,6 +3,7 @@ require 'mysql2'
|
|
3
3
|
|
4
4
|
class Kandata
|
5
5
|
# ActiveRecordを使わないでKandataデータベースにアクセスするためのクラス
|
6
|
+
# ignore :reek:InstanceVariableAssumption:
|
6
7
|
class Database < Mysql2::Client
|
7
8
|
def initialize
|
8
9
|
create_database_if_not_exists
|
@@ -15,8 +16,8 @@ class Kandata
|
|
15
16
|
end
|
16
17
|
|
17
18
|
# ignore :reek:ControlParameter:
|
18
|
-
def load_tsv(filename, force_update)
|
19
|
-
@tsv = Kandata::TsvFile.new(filename)
|
19
|
+
def load_tsv(filename, force_update, headers = nil)
|
20
|
+
@tsv = Kandata::TsvFile.new(filename, headers)
|
20
21
|
|
21
22
|
drop_table if force_update
|
22
23
|
create_table
|
@@ -30,18 +31,17 @@ class Kandata
|
|
30
31
|
# ignore :reek:FeatureEnvy:
|
31
32
|
def create_database_if_not_exists
|
32
33
|
client = Mysql2::Client.new(Kandata::Database::ConnectionInfo.host_and_user)
|
33
|
-
database_name = Kandata::Database::ConnectionInfo.database_name
|
34
34
|
|
35
35
|
begin
|
36
|
-
client.query("SHOW CREATE DATABASE
|
36
|
+
client.query("SHOW CREATE DATABASE `#{database_name}`")
|
37
37
|
rescue Mysql2::Error => error
|
38
38
|
raise error unless error.message == "Unknown database '#{database_name}'"
|
39
|
-
client.query("CREATE DATABASE
|
39
|
+
client.query("CREATE DATABASE `#{database_name}`")
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
def drop_table
|
44
|
-
query("DROP TABLE IF EXISTS
|
44
|
+
query("DROP TABLE IF EXISTS `#{database_name}`.`#{table_name}`")
|
45
45
|
end
|
46
46
|
|
47
47
|
def create_table
|
@@ -50,21 +50,30 @@ class Kandata
|
|
50
50
|
# 後で追加するため一旦削除
|
51
51
|
columns.delete('id')
|
52
52
|
|
53
|
-
columns_text = columns.map { |column| "#{column}
|
53
|
+
columns_text = columns.map { |column| "#{column} TEXT" }.join(',')
|
54
54
|
columns_text = 'id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,' + columns_text
|
55
55
|
|
56
|
-
query("CREATE TABLE
|
56
|
+
query("CREATE TABLE `#{database_name}`.`#{table_name}` (#{columns_text})")
|
57
57
|
end
|
58
58
|
|
59
59
|
def load_data
|
60
|
-
sql = "LOAD DATA LOCAL INFILE '#{@tsv.filename}' INTO TABLE
|
61
|
-
sql += "(#{@tsv.headers.join(',')})"
|
60
|
+
sql = "LOAD DATA LOCAL INFILE '#{@tsv.filename}' INTO TABLE `#{database_name}`.`#{table_name}` IGNORE 1 LINES "
|
61
|
+
sql += "(#{@tsv.headers.map { |column| "`#{column}`" }.join(',')})"
|
62
62
|
|
63
63
|
query(sql)
|
64
64
|
end
|
65
65
|
|
66
66
|
def full_table_name
|
67
|
-
"#{
|
67
|
+
"#{database_name}.#{table_name}"
|
68
|
+
end
|
69
|
+
|
70
|
+
# ignore :reek:UtilityFunction:
|
71
|
+
def database_name
|
72
|
+
Kandata::Database::ConnectionInfo.database_name
|
73
|
+
end
|
74
|
+
|
75
|
+
def table_name
|
76
|
+
@tsv.table_name if @tsv.present?
|
68
77
|
end
|
69
78
|
end
|
70
79
|
end
|
data/lib/kandata/tsv_file.rb
CHANGED
@@ -1,28 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
require 'tempfile'
|
3
|
+
require 'nkf'
|
4
|
+
|
2
5
|
class Kandata
|
3
6
|
# 読み込み用TSVファイル
|
4
7
|
class TsvFile
|
5
|
-
attr_reader :filename, :headers
|
8
|
+
attr_reader :filename, :table_name, :headers
|
9
|
+
|
10
|
+
RESERVED_COLUMNS = ['type'].freeze
|
11
|
+
|
12
|
+
def initialize(filename, custom_headers = nil)
|
13
|
+
@table_name = File.basename(filename).sub('.tsv', '')
|
14
|
+
validate_table_name
|
6
15
|
|
7
|
-
|
8
|
-
@filename = filename
|
9
|
-
|
16
|
+
# TempFileにファイル内容をコピーしてパスを返す
|
17
|
+
@filename = copy_to_tempfile(filename)
|
18
|
+
|
19
|
+
@headers = custom_headers
|
20
|
+
@headers ||= File.open(@filename, 'r').first(&:readline).chomp.split("\t")
|
10
21
|
|
11
|
-
@headers = File.open(@filename, 'r').first(&:readline).chomp.split("\t")
|
12
22
|
validate_headers
|
13
23
|
end
|
14
24
|
|
15
|
-
def
|
16
|
-
raise 'テーブル名に使用できないファイル名です' unless table_name.match?(/^[0-9a-zA-Z$_]+$/)
|
25
|
+
def validate_table_name
|
26
|
+
raise 'テーブル名に使用できないファイル名です' unless @table_name.match?(/^[0-9a-zA-Z$_]+$/)
|
17
27
|
true
|
18
28
|
end
|
19
29
|
|
20
30
|
def validate_headers
|
21
|
-
duplicated_columns = @headers.group_by { |value| value }.reject { |_key, value| value.one? }.keys
|
22
31
|
raise "以下のカラムが複数存在しています #{duplicated_columns}" unless duplicated_columns.empty?
|
23
32
|
|
24
|
-
|
25
|
-
raise "以下のカラム名は使用できません #{
|
33
|
+
raise "以下のカラム名は使用できません #{invalid_columns}" unless invalid_columns.empty?
|
34
|
+
raise "以下のカラム名は使用できません #{RESERVED_COLUMNS}" if include_reserved_name?
|
26
35
|
|
27
36
|
# 現時点では、ミス防止のため、先頭以外にidカラムがあるとエラーとして処理する
|
28
37
|
raise '先頭以外にidカラムがあります' if include_id_column? && @headers[0] != 'id'
|
@@ -30,12 +39,29 @@ class Kandata
|
|
30
39
|
true
|
31
40
|
end
|
32
41
|
|
33
|
-
def
|
34
|
-
|
42
|
+
def duplicated_columns
|
43
|
+
@headers.group_by { |value| value }.reject { |_key, value| value.one? }.keys
|
44
|
+
end
|
45
|
+
|
46
|
+
def invalid_columns
|
47
|
+
@headers.reject { |value| value.match?(/^[0-9a-zA-Z$_]+$/) }
|
48
|
+
end
|
49
|
+
|
50
|
+
def include_reserved_name?
|
51
|
+
RESERVED_COLUMNS.any? { |name| @headers.include?(name) }
|
35
52
|
end
|
36
53
|
|
37
54
|
def include_id_column?
|
38
55
|
@headers.include?('id')
|
39
56
|
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def copy_to_tempfile(filename)
|
61
|
+
Tempfile.open(basename: self.class.name) do |file|
|
62
|
+
file.write(NKF.nkf('-w', File.open(filename, 'r').read))
|
63
|
+
file.path
|
64
|
+
end
|
65
|
+
end
|
40
66
|
end
|
41
67
|
end
|
data/lib/kandata/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kandata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yuya TAMANO
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|