Why DataMapper?

以下,超意訳です.あしからず.
原文:http://datamapper.org/doku.php?id=why_datamapper

      • -

DataMapper は,他の O/R Mapper といくつかの点で異なる.

Identity Map

DB における 1 つの行は,1 つのオブジェクト参照と等しくなるべきである.
とても単純だが,とてもインパクトがある.
もし ActiveRecord で以下のコードを実行した場合,あなたは全て false という結果を見るだろう.
だが DataMapper で同じ事をした場合,全て true になる.

@parent = Tree.find(:first, :conditions => ['name = ?', 'bob'])
 
@parent.children.each do |child|
  puts @parent.object_id == child.parent.object_id
end

Plays Well With Others

DataMapper では,Model にマッピングを定義する.
データストアは,マイグレーションを利用することで,Model とは独立して発展できる.
Model をきちんと書けば,調整とか含めて一切合切を DataMapper が面倒みてくれる.
(上手く訳せなかったけど,たぶんこんな意味???)

Laziness Can Be A Virtue

無限の長さを持ち得るカラム,例えば Text カラムなどは,DB において高価である.
They're generally stored in a different place from the rest of your data. So instead of a fast sequential read from your hard-drive, your data-store has to hop around all over the place to get what it needs.
DataMapper においてこれらのフィールドは,ロードした時に限り default で in-row 関連のように扱われる.


もしあなたがこれを制御したい場合は,lazy オプションに true/false を設定すればよい.
ただし,Text フィールドはデフォルトで lazy-load である.


加えて,Text フィールドの lazy-load は,自動的に賢く行われる.
次の例では,各 animal における notes フィールドの全てをロードするために,2 つのクエリしか発行しない (次の節で説明が出てくる).

animals = Animal.all
animals.each do |animal|
  animal.notes
end

Strategic Eager Loading

DataMapper はデータストアに対し,必要なときに,必要最小限のクエリしか発行しないだろう.
次の例では 2 つのクエリしか発行しないだろう.

zoos = Zoo.all
zoos.each do |zoo|
  # 最初の iteration で DataMapper は,zoos に含まれる全ての要素のために,exhibits の全てをロードする.
  # 1 つのクエリで.

  zoo.exhibits.each do |exhibit|
    # 他の O/R Mapper だと N+1 クエリになっちゃうけど,DataMapper ではそうならない.
    puts "Zoo: #{zoo.name}, Exhibit: #{exhibit.name}"
  end
end

このアイデアは,「オブジェクトのセットをロードしておきながら,その中の1つだけしか使わない,ということはないだろう」というものである.
This should hold up pretty well against a 99% rule.

When you don't want it to work like this, just load the item you want in it's own set. So DataMapper thinks ahead. We like to call it “performant by default”.
この特徴は,単独で "N+1 Query Problem" を無くすことができる.

また DataMapper は,実際のクエリ発行を最後の瞬間まで待つ.

zoos = Zoo.all

これはイテレ-ションを始めるか,もしくは #length のような 'kicker' メソッドを呼び出すまで,クエリは実行されないだろう.
あなたがクエリの結果で何かしようとしない限り,DataMapper は DB アクセスのレイテンシを被ることは無いだろう.


※↓補足

All Ruby, All The Time

(あとで書く...かも)


クエリパスも使える.

Person.all(:links => [:pets], Person.pets.name => 'Pixel')

Open Development

TODO