おがさわらなるひこのオープンソースとかプログラミングとか印刷技術とか

おがさわらなるひこ @naru0ga が技術系で興味を持ったりなんだりしたことをたまーに書くブログです。最近はてなダイアリー放置しすぎて記事書くたびにはてな記法忘れるのではてなブログに移行しました。

クリエイティブ・コモンズ・ライセンス
特に断りがない場合は、本ブログの筆者によるコンテンツは クリエイティブ・コモンズ 表示 - 継承 4.0 国際 ライセンスの下に提供されています。

Ruby初心者がRuby on Rails + Mongoidを試してみた

この記事はMongoDB Advent Calendar 2013の二日目です。

後の人のハードルを下げるために、私はレベルが低い話を。

私の勤務先は中堅SIerでして、そこの小さなチームでつかそうな案件のときはMongoDBを使おうということで、出番を虎視眈々と狙っている次第です。以前は Scala に Play! Framework に MongoDB を組み合わせるという案件をやりまして、そのときのことは↓に書いたりしました。

しかし私の部署の中で最大与党は Ruby on Rails (以下 Rails) で図書館管理アプリを作っているメンバーでして、ここのワークロードが低いときにでもぱっと案件取れるようにするには、Rails で MongoDB 使えますよ! と、説得できないといけません。

しかし Rails といえばなんつっても ORM (Object-Relation Mapper) である Active Record でして、Active Record は ORM というからして、当然 RDBMS を叩くことしか考えられていません。そんなわけで、Active Record 的な I/F を持った ODM (Object-Document Mapper) な Mongoid をちょっとお試ししてみました。

Mongoid とは何か

Mongoid とは何か、ということについては本家のページを参照してください。イントロだけ引用すると:

Mongoid (pronounced mann-goyd) is an Object-Document-Mapper (ODM) for MongoDB written in Ruby.(snip)

The philosophy of Mongoid is to provide a familiar API to Ruby developers who have been using Active Record or Data Mapper, while leveraging the power of MongoDB’s schemaless and performant document-based design, dynamic queries, and atomic modifier operations.

(参考訳)
Mongoid (発音は mann-goyd) はRubyで書かれたMongoDBのオブジェクト・文書マッパー (ODM) です。(略)

Mongoidの哲学はActive RecordやData Mapperに慣れている Ruby 開発者に親しみやすい API を与えつつ、MongoDB のスキーマレスや強力なドキュメントベースデザイン、動的クエリ、アトミックな変更操作などの強みを使えるようにすることです。

このようにMongoidはActive Recordの置き換えを強く意識しているので、Railsエンジニアには使いやすいのではないかと思います。

Mongoidを試す

さすがに実プロダクトのバックエンドを差し替えるほどの Rails スキルはないので、新規プロジェクトで Mongoid を使ったものを作ってみます。私は Rails に詳しくないので新規プロジェクトを作成するのは Rails Tutorial を参考にしました。

rbenv + ruby-build を用いて Rubyは 2.0、Railsは 4.0 を導入した環境で:

rails new mongo_sample_app --skip-active-record

で新規のRailsアプリを生成します。--skip-active-recordがミソ。

そしてGemfileに次の一行を加えます。

gem "mongoid", github: 'mongoid/mongoid'

ここで Github の master を取ってきているのは Mongoid の stable である 3.x 系は Rails4.0 (正確にいうとActive Modelの最新) と依存関係が当たるので gem で普通に入れると非常に古いバージョンが入ってしまうから。これ調べたのちょっと昔 (11月頭ぐらい) なのでもしかしたら今は大丈夫かもしれません。なお、ドキュメントによっては bson_ext という gem が必要と書いてあるものがありますが、この gem は Mongoid 3.x 系で取り込まれたので不要になりました。単に Mongoid だけを指定すればいいです。

次に:

rails g mongoid:config

でconfigファイルを出力。config/mongoid.ymlというファイルが生成されます。開いて中をチェックしてみます。コメントが丁寧に入っているので見ればわかると思うのでここで引き写すことはしませんが、ローカルに MongoDB が動いている環境*1 ならばほぼ素で使えますが、そうでない場合も設定はとても簡単です。今回は深入りしませんけど、Read Preference とか Write Concern などもここで定義できる感じですね。

さてここまでできたら単純に一つモデルを定義して scaffold を生成してみましょう。次のようなモデル User を考えます。

User
nameString
emailString
このモデルおよび scaffold を生成するには以下のようにすれば OK です:

rails g scaffold User name email

なお型指定がないのは、Mongoid はデフォルトの型が文字列と決まっているから。

試しに rails s して localhost:3000/users にアクセスすると、ちゃんとユーザー作成ができるようになります。
ここで注目したいのは

db:migrate が不要なこと。

MongoDB の場合はスキーマ定義も不要であるしデータベースもコレクションにドキュメントをinsertしたところで自動で生成されるので、マイグレーションがいらないのです。正直 Rails のちょっとめんどくさいところってソースいじってるだけじゃ完結しなくて rake コマンド叩かないといけないところだと私は思っているので、これは結構ありがたい気がしてます。カジュアルな MongoDB っぽいなあと。

なお、この段階なら、要素を増やすのももう一度scaffoldの生成を行う (そして、コンフリクトは全部overrideで解決) するだけでよいです。

rails g scaffold User name email nick

さすがに出来合いの View や Controller 使う人はいないと思うのですが、Model だけは上書きしてあとは手書き、というスタイルで、開発途中の要素追加も割と容易なのではないかと思います。なお、View や Controller 側から Model を触るときには当然 Active Model にラップされていますので、Rails に慣れた人なら素直にコーディングできるのではないかな??

そんなわけで「スキーマ定義ができないけれど開発には着手しなければならない」場合、Rails + Mongoid + MongoDB という組み合わせはわりと「アリ」ではないかと思います。


埋め込みドキュメントを使うときとか、あと JOIN をしないといけないときとかについてはまだ試してないですけど、まあそういうことは誰かが書いてくれるでしょう多分。


と、ここまで書いたらモロおんなじ内容が Qiita にあったことに今気づきましたが、知らん顔して投稿することにします。重なっていない部分もあるしね。
あすは key さんですね。よろしくおねがいします!

*1:私の環境は Ubuntu に MongoDB Inc 公式リポジトリを追加してローカルに mongod が動いてます。