ActiveTokyoCabinet 0.1.1

http://activetokyocabi.rubyforge.org/

ActiveTokyoCabinet 0.1.1をリリースしました。

これは何?

ActiveRecordのTokyo(Cabinet|Tyrant)のテーブルデータベースのアダプタです。
TokyoTyrantActiveRecordのように使えるMiyazakiResistanceもあるんですが、アダプタとして実装した方がよりシームレスだろうと思って作ってみました。

使い方

database.ymlの書き方は次の通り。
TykyoCabinetでは1ファイルを1テーブルとしています。
また、TokyoTyrantではサーバ1台を1テーブルとしています。

# TokyoCabinet
development:
  adapter: tokyocabinet
  database: path_of_database_directory
                           # ~~~~~~~~~
# TokyoTyrant
development:
  adapter: tokyotyrant
  database:
    hellos: { host: localhost, port: 1978 }
    tests: { host: localhost, port: 1979 }

サーバ側でスキーマを定義が出来ないので、Modelに定義します。

class Hello < ActiveRecord::Base
  include ActiveTokyoCabinet::TDB

  # define schema information.
  # (string, int, float)
  string :name
  int    :age
end

いくつかの制限を除けば、普通にActiveRecordとして使えます。
使用するSQLも、一般的なSQLとだいたいおんなじ感じです。
offset、limit、order byも使えます。

(20..35).each do |i|
  hello = Hello.new
  hello.name = 'yamada'
  hello.age  = i
  hello.save!
  hello_id = hello.id
end
    
p Hello.find(:all, 
             :conditions => ["name = ? and age > ?", "yamada", 25],
             :order => 'age desc', :limit => 5, :offset => 3)

hello = Hello.find(hello_id)
hello.name = 'yamashita'
hello.save!

制限

Hello.find(:all, :conditions => ["name bw ?", "yama"])
Hello.find(:all, :conditions => ["name ew ?", "mada"])
Hello.find(:all, :conditions => ["name inc ?", "ma"])
Hello.find(:all, :conditions => ["name regexp ?", "^ya.+"])
Hello.find(:all, :conditions => ["name bt (?, ?)", "start", "end")
Hello.find(:all, :conditions => ["name fts ?", "phrase")
  • :join、:include、サブクエリは使えません
  • 検索条件の結合にORを使えません
  • 検索条件にidを含められません。idで検索する場合、idまたはidの配列を引数としてfindを呼び出してください
  • Migrationは使えません
  • TokyoCabinetでも使えますが、現状では複数プロセスの同時アクセスを全く考慮していないので、あまり実用的ではないです。なにか実践的なやり方があれば、どなたか教えてください…
  • あんまりテストできてないです
  • TokyoTyrantはテーブルデータベースで起動してください

中でやってること

ActiveRecordの組み立てたSQLをパースして、Tokyo(Cabinet|Tyrant)の各処理にマップするようにしています。あとは普通のアダプタと同じです。
SQLのパースにはRaccを使っています。