Category : Ruby

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

準備

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

$ gem install mysql2
$ gem install activerecord

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

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, description, category)
    -> values
    -> ("たいとる", "http://hogehogehogehoge.com", "ほげほげディスクリプション", "hatena");

# レコードの更新
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をご確認下さい。

# 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」という2つの関連テーブルを作ってみます。

# 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 で、関連テーブルのデータをオブジェクトとして取得できる。

これまでRailsで楽してたので、いざRubyで組もうと思ったらいろいろ忘れてました。Railsに任せっきりはやはり駄目ですね。特にActiveRecordぱっかり使ってるとSQL文が特に・・・でも楽なんだよなぁ。
次はSinatraの使い方をざっくりまとめます。

(追記)
→ Sinatraの記事はこちら

参考になった書籍など

参考にさせていただいたサイト様