前回Rubyの基本的な文法を少しやったので、あとはネット上からコードを拾ってきて見るのが良いと思うのでいきなりですがDB操作をしてみたいと思います。
実行環境
Windows10 64bit
Eclipse 4.6.0
ruby2.3.1
sqlite3のインストール
コマンドラインで「gem install sqlite3」と入力、エンターキーを押してインストールを開始します。1,2分でインストールが完了します。
コードを書いて実行
DB作成・テーブル作成・値の書き込み・読み込み
GitHub – sparklemotion_sqlite3-ruby_ Ruby bindings for the SQLite3 embedded databaseここに書いているサンプルコードの一部分をコピペした以下のコードを実行してみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
require "sqlite3" fileName = "kan.db" #DBに接続する。ファイルがなければ新規作成する。 db = SQLite3::Database.new(fileName) #テーブルを作成する rows = db.execute <<-SQL create table numbers ( name varchar(30), val int ); SQL #データを挿入する { "one" => 1, "two" => 2, }.each do |pair| db.execute "insert into numbers values ( ?, ? )", pair end #データを表示する db.execute("select * from numbers") do |row| p row end |
しかし以下のエラーが表示されて実行できなかった。
1 2 3 4 5 6 7 8 |
C:/Ruby23-x64/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- sqlite3/sqlite3_native (LoadError) from C:/Ruby23-x64/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require' from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.11-x64-mingw32/lib/sqlite3.rb:6:in `rescue in ' from C:/Ruby23-x64/lib/ruby/gems/2.3.0/gems/sqlite3-1.3.11-x64-mingw32/lib/sqlite3.rb:2:in `' from C:/Ruby23-x64/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `require' from C:/Ruby23-x64/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:127:in `rescue in require' from C:/Ruby23-x64/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:40:in `require' from D:/eclipse_ruby_workspace/hoge/hoge.rb:1:in `' |
調べてみるとどうやらRubyのバージョンが2.3.xであるのがダメらしい。
Ruby2.3.1をアンインストールして、http://rubyinstaller.org/downloads/ここからRuby2.2.5(x64)のインストーラーをDL、インストールした。
さらに「gem uninstall sqlite3」でアンインストールした後、再び「gem install sqlite3」でインストールした。これでRuby2.2のディレクトリにsqlite3がインストールされていればOK。(Ruby2.2をCドライブ直下にインストールした場合、「C:\Ruby22-x64\lib\ruby\gems\2.2.0\gems\sqlite3-1.3.11-x64-mingw32」が存在すればOK.)
あとはEclipseの「ウィンドウ>設定>Ruby>インタープリター」でインストールしたばかりのRubyを追加して適用すればOK。
先程のコードを実行すると以下が出力される。
1 2 |
["one", 1] ["tow", 2] |
これは配列の中身ですね。コードの所々でわからないところがあるので書き出してみます。
1 |
db = SQLite3::Database.new(fileName) |
この部分はSQLite3モジュール内のDatabaseクラスのオブジェクトを生成している。
1 2 3 4 5 6 7 |
rows = db.execute <<-SQL create table numbers ( name varchar(30), val int ); SQL |
この部分はいくつか混ざってて、私がわかりやすい形で書くと
1 2 |
sql = "sql文" rows = db.execute(sql) |
こんな感じになります。<<-SQL …. SQLで囲まれた部分はヒアドキュメントです。以前PHPを一通り見た時に見たはずなんですが忘れていました。Rubyにもあるんですね。
ヒアドキュメントが何かと言えば、複数行の文字列を生成できる書き方?でしょうか。書き方は色々あるようです。
Rubyでヒアドキュメントを使う – Qiita
Ruby のヒアドキュメントすごい – Qiita
メソッドの書き方に関してもちょっとわかりづらかったのですが、引数を括弧内に書かずにスペースを空けて書くこともできるみたいですね。
1 2 |
sql = "sql文" rows = db.execute sql |
みたいに。
1 2 3 4 5 6 |
{ "one" => 1, "tow" => 2, }.each do |pair| db.execute "insert into numbers values (?, ? )", pair end |
{}で囲まれた部分はハッシュオブジェクトですね。生成したハッシュに対してeachメソッドを使用しているみたいです。
ところでハッシュをeachオブジェクトで回す時のこの変数pairのデータにはどういう書き方でアクセスすればよいのでしょうか? 気になったので試してみました。
1 2 3 4 5 6 7 8 |
{ "one" => 1, "tow" => 2, }.each do |pair| p pair[0] p pair[1] end |
このコードを実行すると
1 2 3 4 |
"one" 1 "tow" 2 |
こんな結果になりました。これは配列ですね。
1 2 3 |
db.execute("select * from numbers") do |row| p row end |
これはどういう書き方なのかイマイチわかりません。eachメソッドのような感じもしますけど。
execute(“…”).each do |row| と書き足して実行しても同じように出力されました。もしかして配列やハッシュに対してeachメソッドを使うときはeachを省略できるの?
と思ったけどそうではないようで。ここばかりはわかりません。同じように書いておけば良いのでしょう。
ファイル読み書きディレクトリを変更する
先程のコードでDBが新規作成されたと思いますが、Eclipseの場合デフォルトのファイル書き込み場所はプロジェクトルート直下だと思います。rubyファイルも何もかも。ついでなのでDBを読み書きするディレクトリを変更してみます。
プロジェクトルートに「db」というディレクトリを作成します。スクリプトエクスプローラーでプロジェクト名をクリックし「右クリック>実行>実行の構成」を選択する。「引数」タブの作業ディレクトリを先程作成したdbディレクトリにすればOK。
別にプロジェクトルート直下でもいいんだけどファイル数が多いと邪魔だしね。
既存のDBを使用する
そのまま既存のDBを利用してみます。利用するDBはhttp://aillice-android.com/wp-content/kancolle_timer/db_kanmusu_list/11/kanmusu_list.dbこれにしますか。「鎮守府タイマー」というアプリ内で使用しているものです。
このDBファイルをdbディレクトリに移動させます。
テーブル名は「kanmusu_list」です。
1 2 3 4 5 6 |
require "sqlite3" fileName = "kanmusu_list.db" db = SQLite3::Database.new(fileName) row = db.execute("select * from kanmusu_list") p row[0] |
こんな感じでアクセスできます。ちなみに表示される内容は
1 |
[1, 1, 6, 8, "ながと", "長門", "長門型", "1番艦", "戦艦", 80, 82, 75, 0, 24, 31, 12, 0, "低", 12, "長", 20] |
終わりに
(SQL文の書き方だいぶ忘れていますが…)DB操作自体は割りと簡単にできそうで安心しました。
けど、サンプルコードを拾う度にrubyの多様な書き方で頭を悩ませそうな嫌な予感がします。
そういえば前々回辺りの記事の最後にモジュールがjavaのパッケージと同じものなんじゃね?とか言ってましたけどとんだ勘違いでした。簡単にいえばモジュールはクラスやstaticなメソッドをまとめて定義しておくために使えるみたいです。そういえばstaticなメソッドをどうやって書くかわからなかったんですよね。これからはモジュールの出番が増えそうです。