0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ActiveRecord単体を使ったTSVファイルからMySQLへのデータ移行(ヘッダー除去)

Last updated at Posted at 2020-10-01

はじめに

ActiveRecordを単体で使用して(railsなし)テキストファイルから、データベースへのデータ移行を行いました。今回はタブ区切り形式のデータファイル(TSVファイル)からデータを読み込み、MySQLのデータベースへ格納しました。

目次

0.完成コード
1.ActiveRecordのインストール
2.MySQLへの接続設定
3.クラス定義
4.データの読み込みとレコードの作成
 4-1.with_indexを用いて、ヘッダー部分を除去
 4-2.多重代入を用いたヘッダーの除去
5.プログラムを実行

0.完成コード

posts_to_mysql.rb
require 'active_record'

# DB接続設定
ActiveRecord::Base.establish_connection(
  adapter: 'mysql2',
  host: 'localhost',
  username: 'root',
  database: 'training'
)

# テーブルにアクセスするためのクラスを定義
class Post < ActiveRecord::Base
end

# レコードの作成
File.foreach('posts.txt').with_index do |line, i|
  next if i == 0
  post_with_index = line.chomp.split("\t")
  Post.create(user_id: post_with_index[0], content: post_with_index[1])
end

# レコード取得
p Post.all

1.ActiveRecordのインストール

まずは、ActiveRecordのインストールを行います。


$ gem install activerecord

次に、MySQLに接続するためのアダプタmysql2というgemもインストールします。ここで以下のように普通にインストールを行おうとするとエラーが出てくる場合があります。

$ gem install mysql2

対処法としては、以下のようにライブラリの場所を指定するオプションを付けて実行します。

gem install mysql2 -v '0.5.2' -- --with-ldflags=-L/usr/local/opt/openssl/lib --with-cppflags=-I/usr/local/opt/openssl/include

参考: 
gem install mysql2エラー(Error installing mysql2)
mysql2 gemインストール時のトラブルシュート

2.MySQLへの接続設定

MySQLのデータベースと接続するための設定を書きます。ここでは、MySQLのデータベース名をtrainingとしています。

posts_to_mysql.rb
ActiveRecord::Base.establish_connection(
  adapter: 'mysql2',
  host: 'localhost',
  username: 'root',
  database: 'training'
)

3.クラス定義

trainingデータベースのテーブルにアクセスするためのクラスを定義します。ここでは、postsテーブルにアクセスするため、ActiveRecord::Baseを継承したPostクラスを定義しています。

posts_to_mysql.rb
class Post < ActiveRecord::Base
end

4.データの読み込みとレコードの作成

メインの、データの移行作業を行います。今回読み込むデータ元のpost.txtの最初の行はヘッダーになっているため、データベースにこの行は入らないようにする必要があります。

posts.txt
user_id	content  # ヘッダー行
1	Hello
1	World
2	I'm Paul.
4	😀
5	😂

4-1.with_indexを用いて、ヘッダー部分を除去

こういったヘッダー除去には、Enumeratorクラスに定義されているwith_indexメソッドが活躍します。各行について、読み込みの際に順に番号をつけていって、最初の番号である0を持っていたら、データベースには入れないようにします。これで、最初の行であるヘッダー行の格納を防ぐことができます。

posts_to_mysql
File.foreach('posts.txt').with_index do |line, i|
  next if i == 0
  post_with_index = line.chomp.split("\t")
  Post.create(user_id: post_with_index[0], content: post_with_index[1])
end

p Post.all

EnumeratorであるFile.foreach('posts.txt')にwith_indexメソッドを使うことで、順に番号をつけていっています。そして、番号が0のとき(i == 0)nextで飛ばしています。番号1以降の行は配列post_with_indexに入り、Post.createでmysqlにおけるpostsテーブルのuser_idカラムと、contentカラムに情報が入ります。
Enumeratorという概念は分かりづらいですが、いくつか要素があってそれぞれにメソッドを適用できる準備がされているような状態だと考えています。例えば、配列.eachがEnumeratorオブジェクトです。

####4-2.多重代入を用いたヘッダーの除去

ヘッダー除去の他の方法として、Rubyの多重代入を使うことができます。多重代入については以下の記事を参考にさせていただきました。
Rubyの多重代入あれこれまとめ
変数に * をつけることで、右辺の残り要素全部を配列として受け取ることができます。

x, y, *z = [10, 20, 30, 40]
x #=> 10
y #=> 20
z #=> [30, 40]

多重代入を利用して、headerとpostsという配列にデータを分離し、ヘッダーを除去した上でデータベースに入れていくことができます。

posts_to_mysql.rb
# データを配列posts_with_headerへ格納
posts_with_header = []
File.foreach('posts.txt') do |line|
  posts_with_header << line.chomp.split("\t")
end

# 多重代入でheaderと配列postsに分ける。1個目の要素がheader、2個目以降がpostsに入る。
header, *posts = posts_with_header

# postsをDBに入れていく。
posts.each do |post|
  Post.create(user_id: post[0], content: post[1])
end

# レコード取得
p Post.all

5.プログラムを実行

$ ruby posts_to_mysql.rb
# =>
#<ActiveRecord::Relation [#<Post id: 1, user_id: 1, content: "Hello">, #<Post id: 2, user_id: 1, content: "World">, #<Post id: 3, user_id: 2, content: "I'm Paul.">, #<Post id: 4, user_id: 4, content: "😀">, #<Post id: 5, user_id: 5, content: "😂">]>

MySQLのpostsテーブルにヘッダー以外のデータを移行することができました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?