Skip to content
Newer
Older
100644 153 lines (112 sloc) 5.93 KB
e8b4f3b @sam Importing from old repository.
sam authored
1
2 :include:QUICKLINKS
3
4 = Why DataMapper?
5
6 == Open Development
7
0ba594d @myabc Fixed Ruby 1.9 compatibility (use of : shorthand for 'then') in DataM…
myabc authored
8 DataMapper sports a very accessible code-base and a welcoming community.
e8b4f3b @sam Importing from old repository.
sam authored
9 Outside contributions and feedback are welcome and encouraged, especially
10 constructive criticism. Make your voice heard! Submit a
11 ticket[http://wm.lighthouseapp.com/projects/4819-datamapper/overview] or
12 patch[http://wm.lighthouseapp.com/projects/4819-datamapper/overview], speak up
13 on our mailing-list[http://groups.google.com/group/datamapper/], chat with us
14 on irc[irc://irc.freenode.net/#datamapper], write a spec, get it reviewed, ask
15 for commit rights. It's as easy as that to become a contributor.
16
17 == Identity Map
18
19 One row in the database should equal one object reference. Pretty simple idea.
20 Pretty profound impact. If you run the following code in ActiveRecord you'll
21 see all <tt>false</tt> results. Do the same in DataMapper and it's
22 <tt>true</tt> all the way down.
23
24 @parent = Tree.find(:first, :conditions => ['name = ?', 'bob'])
25
26 @parent.children.each do |child|
27 puts @parent.object_id == child.parent.object_id
28 end
29
30 This makes DataMapper faster and allocate less resources to get things done.
31
32 == Don't Do What You Don't Have To
33
34 ActiveRecord updates every column in a row during a save whether that column
35 changed or not. So it performs work it doesn't really need to making it much
36 slower, and more likely to eat data during concurrent access if you don't go
37 around adding locking support to everything.
38
39 DataMapper only does what it needs to. So it plays well with others. You can
40 use it in an Integration Database without worrying that your application will
41 be a bad actor causing trouble for all of your other processes.
42
43 == Eager Loading
44
45 Ready for something amazing? The following example executes only two queries.
46
98eb950 Minor formatting cleanup on README
Dan Kubb authored
47 zoos = Zoo.all
48 first = zoos.first
e571600 Updated Relationship#initialize to use positional arguments
Dan Kubb authored
49 first.exhibits # Loads the exhibits for all the Zoo objects in the zoos variable.
e8b4f3b @sam Importing from old repository.
sam authored
50
51 Pretty impressive huh? The idea is that you aren't going to load a set of
52 objects and use only an association in just one of them. This should hold up
53 pretty well against a 99% rule. When you don't want it to work like this, just
54 load the item you want in it's own set. So the DataMapper thinks ahead. We
55 like to call it "performant by default". This feature single-handedly wipes
56 out the "N+1 Query Problem". No need to specify an <tt>include</tt> option in
57 your finders.
58
59 == Laziness Can Be A Virtue
60
61 Text columns are expensive in databases. They're generally stored in a
62 different place than the rest of your data. So instead of a fast sequential
63 read from your hard-drive, your database server has to hop around all over the
64 place to get what it needs. Since ActiveRecord returns everything by default,
65 adding a text column to a table slows everything down drastically, across the
66 board.
67
68 Not so with the DataMapper. Text fields are treated like in-row associations
69 by default, meaning they only load when you need them. If you want more
70 control you can enable or disable this feature for any column (not just
71 text-fields) by passing a @lazy@ option to your column mapping with a value of
72 <tt>true</tt> or <tt>false</tt>.
73
0ba594d @myabc Fixed Ruby 1.9 compatibility (use of : shorthand for 'then') in DataM…
myabc authored
74 class Animal
75 include DataMapper::Resource
76 property :name, String
77 property :notes, DataMapper::Types::Text, :lazy => false
e8b4f3b @sam Importing from old repository.
sam authored
78 end
79
80 Plus, lazy-loading of text fields happens automatically and intelligently when
81 working with associations. The following only issues 2 queries to load up all
82 of the notes fields on each animal:
83
98eb950 Minor formatting cleanup on README
Dan Kubb authored
84 animals = Animal.all
85 animals.each do |pet|
e8b4f3b @sam Importing from old repository.
sam authored
86 pet.notes
87 end
88
89 == Plays Well With Others
90
91 In ActiveRecord, all your columns are mapped, whether you want them or not.
92 This slows things down. In the DataMapper you define your mappings in your
93 model. So instead of an _ALTER TABLE ADD COLUMN_ in your Database, you simply
94 add a <tt>property :name, :string</tt> to your model. DRY. No schema.rb. No
95 migration files to conflict or die without reverting changes. Your model
96 drives the database, not the other way around.
97
98 Unless of course you want to map to a legacy database. Raise your hand if you
99 like seeing a method called <tt>col2Name</tt> on your model just because
100 that's what it's called in an old database you can't afford to change right
101 now? In DataMapper you control the mappings:
102
0ba594d @myabc Fixed Ruby 1.9 compatibility (use of : shorthand for 'then') in DataM…
myabc authored
103 class Fruit
104 include DataMapper::Resource
98eb950 Minor formatting cleanup on README
Dan Kubb authored
105 set_table_name 'frt'
0ba594d @myabc Fixed Ruby 1.9 compatibility (use of : shorthand for 'then') in DataM…
myabc authored
106 property :name, String, :column => 'col2Name'
e8b4f3b @sam Importing from old repository.
sam authored
107 end
108
109 == All Ruby, All The Time
110
111 It's great that ActiveRecord allows you to write SQL when you need to, but
112 should we have to so often?
113
114 DataMapper supports issuing your own SQL, but it also provides more helpers
115 and a unique hash-based condition syntax to cover more of the use-cases where
116 issuing your own SQL would have been the only way to go. For example, any
117 finder option that's non-standard is considered a condition. So you can write
118 <tt>Zoo.all(:name => 'Dallas')</tt> and DataMapper will look for zoos with the
119 name of 'Dallas'.
120
121 It's just a little thing, but it's so much nicer than writing
122 <tt>Zoo.find(:all, :conditions => ['name = ?', 'Dallas'])</tt>. What if you
123 need other comparisons though? Try these:
124
125 Zoo.first(:name => 'Galveston')
126
e571600 Updated Relationship#initialize to use positional arguments
Dan Kubb authored
127 # 'gt' means greater-than. We also do 'lt'.
128 Person.all(:age.gt => 30)
e8b4f3b @sam Importing from old repository.
sam authored
129
130 # 'gte' means greather-than-or-equal-to. We also do 'lte'.
131 Person.all(:age.gte => 30)
132
133 Person.all(:name.not => 'bob')
134
135 # If the value of a pair is an Array, we do an IN-clause for you.
136 Person.all(:name.like => 'S%', :id => [1, 2, 3, 4, 5])
137
e571600 Updated Relationship#initialize to use positional arguments
Dan Kubb authored
138 # An alias for Zoo.find(11)
139 Zoo[11]
e8b4f3b @sam Importing from old repository.
sam authored
140
d70e882 Another small formatting cleanup of README
Dan Kubb authored
141 # Does a NOT IN () clause for you.
142 Person.all(:name.not => ['bob','rick','steve'])
e8b4f3b @sam Importing from old repository.
sam authored
143
144 See? Fewer SQL fragments dirtying your Ruby code. And that's just a few of the
145 nice syntax tweaks DataMapper delivers out of the box...
146
147 == Better Is Great, But Familiar Is Nice
148
149 The DataMapper also supports a lot of old-fashioned ActiveRecord syntax. We
150 want to make it easy for you to get started, so aside from mapping your
151 columns and changing the base-class your models inherit from, much of AR
152 syntax for finders are supported as well, making your transition easy.
Something went wrong with that request. Please try again.