Ruby（+ ActiveRecord）でMysqlを使うためのメモ

Rubyのフレームワークであるsinatraを使う際、DBを扱う処理を再学習したのでざざっとまとめてみました。

## 元記事
下記エントリの転載になります。
* [Ruby（+ ActiveRecord）でMysqlを使うためのメモ](http://www.rokurofire.info/2013/11/11/ruby_db/)

## 準備
mysqlを使えるようにしておき、必要なgemも入れておきます。

```
$ gem install mysql2
$ gem install activerecord

#エラーが出る場合はまず下記とかを試したりする
$ sudo yum info mysql-devel
```

##mysqlの基本的なコマンドを確認

```mysql
# DB名：dbname_development
# テーブル名：items

# DBの作成
mysql> create database dbname_development;

# テーブルの作成
mysql> create table items(
	-> id integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
	-> title VARCHAR(255) NOT NULL,
	-> link VARCHAR(500) NOT NULL,
	-> created_at DATETIME NOT NULL,
	-> updated_at DATETIME NOT NULL
	-> );

mysql> desc items;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| title       | varchar(255) | NO   |     | NULL    |                |
| link        | varchar(500) | NO   |     | NULL    |                |
| created_at  | datetime     | NO   |     | NULL    |                |
| updated_at  | datetime     | NO   |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+


# カラム追加
mysql> alter table items add entrydate datetime;

# レコードの追加
mysql> insert into items
    -> (title, link)
    -> values
    -> ("たいとる", "http://hogehogehogehoge.com");

# レコードの更新
mysql> update items set title="ほげほげ" WHERE id = 1;

# DB削除
mysql> drop database dbname_development;

# レコード削除
mysql> delete from items where id < 213;

```
上記コマンドを再確認しておく。

##Rubyで普通にmysqlを使う
queryメソッドの中に、sqlのコマンドをそのまま書いていく感じですね。

```app.rb
# アダプターに"myslq2"を使います
require 'mysql2'

# mysqlに接続
# host、username、password、データベース名を指定
client = Mysql2::Client.new(:host => "localhost", :username => "username", :password => "passwd", :database => "dbname_development")

# レコードの追加
client.query("insert into items (title, link) values ('たいとる', 'http://hogehogehogehoge.com')")

# レコードの追加（プレースホルダ）
title = "たいとる"
link = "http://hogehogehogehoge.com"
client.query("insert into items (title, link) values ('#{title}', '#{link}')")

# レコードを取得して表示
client.query("SELECT * FROM items").each do |e1|
  puts e1
end

```


##Ruby + ActiveRecord でmysqlを使ってみる

Railsでお世話になったAcriveRecordを使ってみます。
・・・その前に、DB接続情報を別ファイル化しておくと便利。

```database.yml
# developmentとproductionで環境を分けて書いておくとよい？

db:
  development:
    adapter: mysql2
    encoding: utf8
    host: localhost
    database: dbname_development
    username: username
    password: passwd
    socket: /var/run/mysqld/mysqld.sock	#環境によって異なる
  production:
    adapter: mysql2
    encoding: utf8
    ・・・
```

```app.rb
require 'active_record'
require 'mysql2'

# 上で作ったDB設定ファイルの読み込み
# ここではdev環境を読み込み
config = YAML.load_file('./database.yml')
ActiveRecord::Base.establish_connection(config["db"]["development"])

# モデルのクラスを宣言
class Item < ActiveRecord::Base
	# バリデーションはここに記述
	validates_presence_of :title
	validates_presence_of :link
end

@entries #DBに登録したいデータ
@entries.each do |entry|
	item = Item.new
	item.title = entry.title
	item.link = entry.link

	# DBに保存
	item.save
end
```

####ループのINSERT処理にBULK INSERTを使う

バルクインサートするためのgem "activerecord-import" があるのでそれも使ってみます。
ループでデータを登録する時、SQL文の発行が少なくなります。詳しくは参考URLをご確認下さい。

* [参考 ActiveRecordで複数レコード、BULK INSERTする方法とパフォーマンスについて](http://qiita.com/xend/items/79184ded56158ea1b97a)

```app.rb
require 'active_record'
require 'mysql2'

# これを追加
require 'activerecord-import'

config = YAML.load_file('./database.yml')
ActiveRecord::Base.establish_connection(config["db"]["development"])

class Item < ActiveRecord::Base
	validates_presence_of :title
	validates_presence_of :link
end

# 配列を1個作る
insertData = []
@entries #DBに登録したいデータ
@entries.each do |entry|
  item = Item.new
  item.title = entry.title
  item.link = entry.link
  item.created_at = entry.dc_date

  # 配列にpush
  insertData << item
end

# importメソッドでDBに保存
Item.import insertData
```

##ActiveRecordでリレーショナルなDBを使う

「item」と「categories」という２つの関連テーブルを作ってみます。

```mysql
# itemテーブル作成
# category_id というカラムを作る
mysql> create table items(
	-> id integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
	-> category_id integer default NULL,
	-> created_at DATETIME NOT NULL,
	-> updated_at DATETIME NOT NULL
	-> );

# categoriesテーブル作成
mysql> create table categories(
	-> id integer NOT NULL AUTO_INCREMENT PRIMARY KEY,
	-> name VARCHAR(50)
	-> );
```

```app.rb
# モデルクラス Item
class Item < ActiveRecord::Base
	belongs_to :category
end

# モデルクラス Category
class Category < ActiveRecord::Base
	has_many :items
end

# Item belongs_to category
# category has_many items
# という関係を作る


# カテゴリオブジェクトを取得
# 今回は name が 'hogehoge'のものを取得
category = Category.where(:name => 'hogehoge').first

item = Item.new
item.category = category
# item.categoryに、取得したカテゴリのオブジェクトを指定

item.save

item.category.name # 'hogehoge'
# item.category で、関連テーブルのデータをオブジェクトとして取得できる。

```

##参考にさせていただいたサイト様
* [参考 Sinatra+ActiveRecord+MySQLで、簡単APIサーバ構築](http://qiita.com/u1_fukui/items/88c10d4d530ec6fbaaa1)
* [参考 Ruby,MySQLの環境を構築する(Linux版)](http://qiita.com/u1_fukui/items/c9f3d8ca69a4ab0b27cb)
* [参考 RubyでMySQLに繋ぐためのruby-mysqlとmysql2](http://d.hatena.ne.jp/tagomoris/20111210/1323502295)
* [参考 ActiveRecordで複数レコード、BULK INSERTする方法とパフォーマンスについて](http://qiita.com/xend/items/79184ded56158ea1b97a)