マグカップの裏

プログラムとか、思ったこととか、料理とか

RubyからSQLiteを触るためにSequelを使ってみた話 その1

その2があるとはいってない。

SQLiteを使う

RubyからSQLiteを使うには下記コマンドでSQLiteのGemをインストールして

gem install sqlite3

こんな感じで書く

require 'sqlite3'

db = SQLite3::Database.new("test.db")

db.execute(select * hogehogehoge)

db.close

SQLが適当だけどこんな感じ。
Rubyという言語で書かれたソースコードの中に、SQLという言語ではないにしろ別の次元のコマンドが入ってくるのは気持ち悪い。
そういう場面で使われるのがORMと言われる、ORマッピングとか言われる手法。
Ruby on Railsを使っている方ならActive Recordがそれ。
今回は私はRoRを使ってない場面でSQLをたたいていたのでSequelを使った方法を記す。

Sequelを使う

まずはGemをインストール

gem install sequel

サンプルコードは下記。

require 'sqlite3'
require 'sequel'

#何かオプションを指定する場合は下記に追記する
options = {}

#DBに接続
db = Sequel.sqlite('/databasepath' , options)

#テーブルを作って適当にフィールドを追加
db.create_table :items do
  primary_key :id
  String :name
  Float :price
end

#データセットをitemsテーブルから取得
items = db[:items]

#適当な値を挿入する
items.insert(:name => 'test', :price => rand * 100)

#アイテムの数を表示してみる
puts "item : #{items.count}"


上記は公式ページにも、どこにでも載っている話なので簡単にできるはず。
今回Sequelを利用しようと思った動機が既存のDBをいじいじするに当たってSQLを書かずに済めば最高だなと思ったからなので、新しくDBを作るとか入らない。
結果下記のようになって、実行した。

require 'sqlite3'
require 'sequel'

#何かオプションを指定する場合は下記に追記する
options = {}

#DBに接続
db = Sequel.sqlite('/databasepath' , options)

#データセットをitemsテーブルから取得
items = db[:items]

#アイテムの数を表示してみる
puts "item : #{items.count}"

普通に動きますね。データベースのパスには気を付けましょう。

日本語の取り扱い

自分の持っていた既存DBをいじろうとしたら日本語が文字化けした。
DBはUTF-8で書いてるしコードの行頭でコーディングを指定してもダメ。
何がだめなのかと思ったらSequelはデフォルトだとASCIIだか何だかで見ているようだ。

require 'sqlite3'
require 'sequel'

#何かオプションを指定する場合は下記に追記する
options = {}

#DBに接続
db = Sequel.sqlite('/databasepath' , options)

#データセットをitemsテーブルから取得
items = db[:items]

#アイテムの数を表示してみる
puts "item : #{items.count}"

name = items[:name]
puts name.encode

force_encodingプラグインをサブクラスを定義して適用、そのサブクラスを使えばコーディングをUTF-8にできるとか、データセットで.force_encodingをたたけばUTF-8にできるとかいろいろ記事を見たけどどれもうまくいかない/肌に合わないので下記の対処法をとった。

require 'sqlite3'
require 'sequel'

#何かオプションを指定する場合は下記に追記する
options = {:encoding=>"utf8"}

#DBに接続
db = Sequel.sqlite('/databasepath' , options)

#データセットをitemsテーブルから取得
items = db[:items]

#アイテムの数を表示してみる
puts "item : #{items.count}"

name = items[:name]
puts name.encode

やったぜ。
SQLに比べて直感的にデータを持って来たり突っ込んだりできそうだし、これはありなツールかな。