友達と遊びに行くつもりでいたらなんかみんな都合合わないとかでお流れになりそうな雰囲気なので、せっかくだから久々にMerbでもいじってみることにした。ん?コミケ?行ってないよ。月曜に有給取ったら職場の人に「週末は戦場に行くので週明けに戦士の休息ですね、わかります」的なリアクションをされたんだけど、いや、別にそういうわけじゃ…。わかんないけど。明日暇に耐え兼ねて行くかもしんないけどさっ!うう…。
思い付きでupdateするな俺のバカ
とりあえず以前の記事で軽く動かしてみる程度はやったものの、MerbもDataMapperもしばらく見てない間に更新されてて、深く考えずにgem updateしたらハマった。Merb本体のバージョンが0.9.4に上がってて、Merbをアップデートしたらextlibのバージョンも0.9.4になっちゃったんだけど、DataMapperのバージョンは0.9.3までしか上がってない。gemのdatamapperが依存してるdata_objectsがextlibの0.9.3を要求する(dependencyが'= databjectsのバージョン'になってる)ため、 「extlibを一旦0.9.3にしてからdata_objects、datamapper、merb_datamapperをアップデート」してみた。
入るには入るんだけど、もちろんextlibが0.9.3のままだと最新のMerbが動かないし、extlibを0.9.4にするとこんどはdatamapperがrequireできない。うがー。ActiveRecordやSequelを使うのも考えたけど、そもそもARを使いたくないからDataMapperを試しているのでARは無いし、Sequelも面白そうなんだけど、Merbのプラグイン?で使ってみたいのがARかDataMapperを想定してるのでSequelは使えない。ので却下。ソースをいじるとかも考えたけど、無意味に面倒な上危ないので却下。どうせリスクがあるんならedge版入れちゃえ、そもそも実験だし、てことでgithubからDataMapperの最新版取ってきて入れた。手順はMerb wikiを見ながらやってみた。
$sake -i http://github.com/dkubb/dm-dev/tree/master/dm-dev.sake?raw=true $ sake dm:clone $ cd dm $ sake dm:install
DataMapperの0.9.4があっさり入りやがった。ぬーん。とりあえず今のところ問題なく動いてる様子。DataMapperがMerb本体に深く影響されるのはなんだか納得行かないんだけど、ARだってRailsにべったりだしなぁと考え直すことにする。
なにはともあれdatabase.yml
とりあえずアプリの雛形を作る。
$merb-gen app --orm datamapper sample
ARが本体の一部であるRailsと違って、O/Rマッパーが本体と分離してるMerbはこの時点ではdatabase.ymlとかmodelsディレクトリとかは作られない。
$rake -T | grep dm rake dm:db:automigrate # Perform automigration rake dm:db:autoupgrade # Perform non destructive automigration rake dm:db:create # Create the database (postgres only) rake dm:db:database_yaml # Create a sample database.yml file rake dm:db:drop # Drop the database (postgres only) rake dm:db:migrate # Migrate the database to the latest version rake dm:db:migrate:down[version] # Migrate down using migrations rake dm:db:migrate:up[version] # Migrate up using migrations rake dm:db:reset # Drop the database, and migrate from scr... rake dm:sessions:clear # Clears sessions rake dm:sessions:create # Perform automigration for sessions $rake dm:db:database_yaml
これでconfig/database.yml.sampleが出来るので、それをコピーして弄る。中身はRailsでアプリ作ったことある人なら見慣れてるであろうデータベースの設定なので、適当にいじる。
# config/database.yml --- development: &default adapter: mysql encoding: utf8 database: sample_development username: user password: password host: localhost
そうしたら、
$merb-gen model user Generating with model generator: [ADDED] spec/models/user_spec.rb [ADDED] app/models/user.rb
しておいて、app/models/user.rbを、
# app/models/user.rb class User include DataMapper::Resource property :id, Integer, serial => true property :name, String, nullable => false end
のようにいじった上で、rake dm:db:automigrateする。これで、DBを適切に設定してあればidとnameというカラムを持ったusersテーブルが出来てるはず。とりあえずここまでできたらmerb -i(Railsで言うところscript/console)とかやっていろいろ遊んでみるといい。
repositoriesってなんぞ
いじってる途中で気付いたんだけど、database.yml.sampleの中にこのような記述が。
development: &defaults # These are the settings for repository :default adapter: postgres database: sample_development username: the_user password: secrets host: localhost # Add more repositories # repositories: # repo1: # adapter: postgresql # database: sample_development # username: the_user # password: secrets # host: localhost # repo2: # ...
調べたら、repositories以下に上のと同じ形式でdbの設定を書いて置くとそれを使って接続できる様子。ふむふむ。それなら、とさっきのdatabase.ymlをちょこっと書き換えてみる。
# config/database.yml --- development: &default adapter: mysql encoding: utf8 database: sample_development username: user password: password host: localhost repositories: slave: adapter: mysql encoding: utf8 database: sample_development_slave username: user password: password host: localhost
これでとりあえずOK。slave、にしたのはdefaultの設定のDBからレプリケーションしてるスレーブのサーバを想定してるんだけど、そもそも全然用途の違う別のDBでもいい。で、使うときはこんなかんじ。
# マスターのサーバから取ってくる user = User.first # こっちはスレーブから取ってくる user_s = User.first(:repository => repository(:slave))
おお。簡単だ。もうちょい説明すると、allとかfirstとかのfindしてくる系統のメソッドに、{:repository => DataMapper::Repositoryのオブジェクト}って引数を渡してやると、そのDB設定で探してくる。database.ymlの設定からDataMapper::Repositoryのオブジェクトを取得するには、repository(設定名)というメソッドを使う。
毎回これをやると面倒なので、参照用のときは必ず:slaveから取ってくるようなメソッドをUserに生やしておくといいかもしれない。逆でもいいな。更新が必要なときだけマスターを見るようにしとくとか。こっちの方が安心か。おそらくモデル単位でどこのリポジトリを使うかを設定できるはずなので、普通のデータは:defaultのDBに入れておいて、あるモデルは:portalに入れておく、とかもできる。DataMapper::Repositoryは動的に生成できるので、分散もそんなに難しくなさそうだ。Rails+ARだと多分プラグインを使わないとできなかったと思うけど、標準でこの機能が付いてるMerb+DataMapperはなかなか素敵。…いや、そう聞いてたからDataMapperを試してみたくなったんだけども。最初からこれが言いたかっただけだったりする。
次はmerb_openidでも
ユーザ認証にOpenIDを使おうと思ってruby-openidを使ってあれこれ試行錯誤してる最中に、merb_openidというgemがあることに気付いた。これを使えば簡単にOpenID認証するコントローラが書けそう。明日あたり試してみよう。