22
Rubyとデータベースとの連携技術 Rubyとデータベースとの連携技術 1 © Tamotsu FURUYA, All rights reserved. K-Ruby, July 28, 2011 Ruby Ruby とデータベースとの連携技術 とデータベースとの連携技術 Integration Technology of Ruby and Database 鹿児島大学 学術情報基盤センター 学術情報処理研究部門 古屋 保 [email protected]

Integration Technology of Ruby and DB

Embed Size (px)

DESCRIPTION

Rubyとデータベースの連携技術

Citation preview

Page 1: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

1© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

RubyRubyとデータベースとの連携技術とデータベースとの連携技術Integration Technology of Ruby and Database

鹿児島大学 学術情報基盤センター学術情報処理研究部門古屋 保[email protected]

Page 2: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

2© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

内容内容● 1. データベース連携概要● 2. MySQLバインディングによる連携● 3. ActiveRecordによる連携

Page 3: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

3© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

1. 1. データベース連携概要データベース連携概要● RubyとMySQLデータベースとの連携

– データベース抽象レイヤを使用せず,直接バインディングを使用してみる.(SQLを記述する必要がある)

「mysql2」…MySQL用のバインディングGem(https://github.com/brianmario/mysql2)

#MySQLのバインディングをインストールする$ gem install mysql2

Page 4: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

4© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

1. 1. データベース連携概要データベース連携概要● Rubyとデータベースとの連携

– ほとんどのDBMSと連携可能 MySQL,PostgreSQL,Oracle,Microsoft SQL

Server,DB2,SQLite 各データベースAPIへのバインディングをGemで提供

– データベース抽象レイヤ(ActiveRecord) DBの違いを意識することなくコーディング可能.

Page 5: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

5© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

2. MySQL2. MySQLバインディングによる連携バインディングによる連携● 連携するデータベース(テーブル)

– 「students」テーブル(予めmysqlツールで作成)mysql> use test;mysql> CREATE TABLE students (-> id CHAR(11) NOT NULL,-> name VARCHAR(40),-> e_mail VARCHAR(80),-> PRIMARY KEY (id)->);

Page 6: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

6© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

2. MySQL2. MySQLバインディングによる連携バインディングによる連携● プログラム例

# -*- coding: utf-8 -*-require 'mysql2'

# ユーザ dbuser で MySQL の test データベースに接続する.client = Mysql2::Client.new( :host => "localhost", :database => "test", :username => "dbuser", :password => "pass" )

# SQLを実行し結果セットを得る.results = client.query("SELECT * FROM students")

Page 7: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

7© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

2. MySQL2. MySQLバインディングによる連携バインディングによる連携● プログラム例

# 結果セットから全レコードのカラムの値をイテレータで取得する.results.each do |row| printf "%s\t%s\t%s\n", row["id"], row["name"], row["e_mail"]end

# データベースと接続をクローズする.client.close

$ ruby dbaccess.rb1234567891 鹿児島太郎 [email protected] 薩摩花子 [email protected] 西郷隆盛 [email protected]

Page 8: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

8© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● ActiveRecord

– データベース抽象レイヤのモジュール– Ruby on Railsを構成するライブラリ群の1つ– O/Rマッピング(Object / Relation Mapping)ライブラリ

Page 9: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

9© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● O/Rマッピング

– データベースのレコードとRubyのオブジェクトをマップする– テーブルのフィールドが、オブジェクトの属性となり,フィー

ルド名がそのままアクセサとして定義される.

Page 10: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

10© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● プログラム例(ActiveRecord編)

# -*- coding: utf-8 -*-require 'active_record'

# 1.8系 # require 'rubygems' # require 'activerecord'

# データベースとの接続ActiveRecord::Base.establish_connection(

:adapter => 'mysql2', # 使用するDBはMySQLデータベース :host => 'localhost', :database => 'test', :username => 'dbuser', :password => 'pass')

(次のスライドへ続く...)

Page 11: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

11© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● プログラム例(ActiveRecord編)

# O/Rマッピングclass Student < ActiveRecord::Baseend

students = Student.find(:all)students.each do |res| printf "%s\t%s\t%s\n", res.id, res.name, res.e_mailend

$ ruby dbaccess.rb1234567891 鹿児島太郎 [email protected] 薩摩花子 [email protected] 西郷隆盛 [email protected]

id,name,e_mail等の属性メソッドは定義してないのにも関わらず...

id,name,e_mail等の属性メソッドは定義してないのにも関わらず...

Page 12: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

12© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● Conversion over Configuration(CoC)

– 「設定よりも規約」(Railsの哲学)– XMLファイルなどのコンフィグはいらない– すべては命名規約に従うこと

Page 13: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

13© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● YAMLファイルの利用

– YAML (YAML Ain't Markup Language)

– 構造化されたテキストフォーマット– Railsでは config/database.yml で利用

development_test: adapter: mysql2 host: localhost database: test username: dbuser password: pass socket: /opt/local/var/run/mysql5/mysqld.sock encoding: utf8 pool: 5

YAMLファイルの例: database.yml(MySQL用)

Page 14: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

14© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● プログラム例(ActiveRecord,YAML利用)

# -*- coding:utf-8 -*-require 'active_record'

# YAMLを利用したデータベースの接続ActiveRecord::Base.configurations = YAML.load_file('database.yml')ActiveRecord::Base.establish_connection('development_test')

class Student < ActiveRecord::Baseend

students = Student.find(:all)students.each do |res| printf "%s\t%s\t%s\n", res.id, res.name, res.e_mailend

Page 15: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

15© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● findメソッドの使用法

例えば...result = Student.find(2)

これは次のSQL文と同等であるSELECT * FROM students WHERE id = 2

※プライマリキーフィールドは「id」というフィールド名でなければNG

解決策class Student < ActiveRecord::Base

set_table_name 'gakusei' # テーブル名は任意でもOK

set_primary_key 's_code' # プライマリキーは任意でもOKend

Page 16: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

16© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● もうSQLは書かなくても良い?

さらに条件をつけて抽出したい場合は...result = Student.find(:all,

:conditions => [ 'name = ?', '鹿児島太郎' ])

SELECT * FROM students WHERE name = '鹿児島太郎'

find以外にも次のようなメソッドも準備されている...result = Student.find_by_name("鹿児島太郎")

さらにレコードの新規追加も...student = Student.new(:id => '1234567894',

:name =>"川内次郎", :e_mail => '[email protected]')

student.save

Page 17: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

17© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

3. ActiveRecord3. ActiveRecordによる連携による連携● ホントにSQLは書かなくても良い?

複雑なクエリーは,直接SQLで書くことも可能...

result = Student.find_by_sql("SELECT * FROM students WHERE name LIKE '%太郎%' AND e_mail LIKE '%jp%'")

まとめ...● 規約に従えばきちんとO/Rマッピングしてくれる.● マッピングできれば用意されたメソッドで結果セットを得られる.● 結果セットから属性メソッドでフィールドデータを得られる.● 極力SQLを書かなくて済む● データベースをいつでも交換できる

その他...● DMLだけでなくDDLも可能(Migrationクラス)

Page 18: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

18© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

4. 4. おまけおまけ● テーブルのJOIN

id name e_mail

1234567891 鹿児島太郎 [email protected]

1234567892 薩摩花子 [email protected]

1234567893 西郷隆盛 [email protected]

id name teacher

S01 情報科学入門 山田太郎S02 エンドユーザ実習 鈴木一郎S03 応用数学 松井秀喜

student_id subject_id rating

1234567891 S02 A

1234567891 S03 B

1234567892 S01 C

1234567893 S02 B

students(学生) subjects(科目)

courses(履修)

1

多 多

1

Page 19: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

19© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

4. 4. おまけおまけ● 結合ビュー

student_id name subject_id name rating

1234567891 鹿児島太郎 S02 エンドユーザ実習 A

1234567891 鹿児島太郎 S03 応用数学 B

1234567892 薩摩花子 S01 情報科学入門 C

1234567893 西郷隆盛 S02 エンドユーザ実習 B

mysql> SELECT student_id, students.name, subject_id,  -> subjects.name, rating -> FROM students JOIN (courses JOIN subjects -> ON courses.subject_id = subjects.id ) -> ON students.id = courses.student_id;

Page 20: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

20© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

4. 4. おまけおまけ● テーブルのJOIN

id name e_mail

1234567891 鹿児島太郎 [email protected]

1234567892 薩摩花子 [email protected]

1234567893 西郷隆盛 [email protected]

id name teacher

S01 情報科学入門 山田太郎S02 エンドユーザ実習 鈴木一郎S03 応用数学 松井秀喜

student_id subject_id rating

1234567891 S02 A

1234567891 S03 B

1234567892 S01 C

1234567893 S02 B

students(学生) subjects(科目)

courses(履修)has_many :course has_many :course

belongs_to :student belongs_to :subject

Page 21: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

21© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

4. 4. おまけおまけ● テーブル間リレーションを意識した定義

class Student < ActiveRecord::Base has_many :courseend

class Subject < ActiveRecord::Base has_many :courseEnd

class Course < ActiveRecord::Base belongs_to :student belongs_to :subjectend

Page 22: Integration Technology of Ruby and DB

Rubyとデータベースとの連携技術Rubyとデータベースとの連携技術

22© Tamotsu FURUYA, All rights reserved.K-Ruby, July 28, 2011

4. 4. おまけおまけ● 結合結果の出力

courses = Course.find(:all, :include => [:student, :subject])courses.each do |res|

printf "%s\t%s\t%s\t%s\t%s\n", res.student_id, res.student.name,

res.subject_id, res.subject.name, res.ratingend

$ ruby dbaccess.rb1234567891 鹿児島太郎 S02 エンドユーザ実習 A1234567891 鹿児島太郎 S03 応用数学 B1234567892 薩摩花子 S01 情報科学入門 C1234567893 西郷隆盛 S02 エンドユーザ実習 B