datamapper 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/CHANGELOG +65 -0
  2. data/README +193 -1
  3. data/do_performance.rb +153 -0
  4. data/environment.rb +45 -0
  5. data/example.rb +119 -22
  6. data/lib/data_mapper.rb +36 -16
  7. data/lib/data_mapper/adapters/abstract_adapter.rb +8 -0
  8. data/lib/data_mapper/adapters/data_object_adapter.rb +360 -0
  9. data/lib/data_mapper/adapters/mysql_adapter.rb +30 -179
  10. data/lib/data_mapper/adapters/postgresql_adapter.rb +90 -199
  11. data/lib/data_mapper/adapters/sql/coersion.rb +32 -3
  12. data/lib/data_mapper/adapters/sql/commands/conditions.rb +97 -128
  13. data/lib/data_mapper/adapters/sql/commands/load_command.rb +234 -231
  14. data/lib/data_mapper/adapters/sql/commands/loader.rb +99 -0
  15. data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +30 -0
  16. data/lib/data_mapper/adapters/sql/mappings/column.rb +68 -6
  17. data/lib/data_mapper/adapters/sql/mappings/schema.rb +6 -3
  18. data/lib/data_mapper/adapters/sql/mappings/table.rb +71 -42
  19. data/lib/data_mapper/adapters/sql/quoting.rb +8 -2
  20. data/lib/data_mapper/adapters/sqlite3_adapter.rb +32 -201
  21. data/lib/data_mapper/associations.rb +21 -7
  22. data/lib/data_mapper/associations/belongs_to_association.rb +96 -80
  23. data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +158 -67
  24. data/lib/data_mapper/associations/has_many_association.rb +96 -78
  25. data/lib/data_mapper/associations/has_n_association.rb +64 -0
  26. data/lib/data_mapper/associations/has_one_association.rb +49 -79
  27. data/lib/data_mapper/associations/reference.rb +47 -0
  28. data/lib/data_mapper/base.rb +216 -50
  29. data/lib/data_mapper/callbacks.rb +71 -24
  30. data/lib/data_mapper/{session.rb → context.rb} +20 -8
  31. data/lib/data_mapper/database.rb +176 -45
  32. data/lib/data_mapper/embedded_value.rb +65 -0
  33. data/lib/data_mapper/identity_map.rb +12 -4
  34. data/lib/data_mapper/support/active_record_impersonation.rb +12 -8
  35. data/lib/data_mapper/support/enumerable.rb +8 -0
  36. data/lib/data_mapper/support/serialization.rb +13 -0
  37. data/lib/data_mapper/support/string.rb +1 -12
  38. data/lib/data_mapper/support/symbol.rb +3 -0
  39. data/lib/data_mapper/validations/unique_validator.rb +1 -2
  40. data/lib/data_mapper/validations/validation_helper.rb +18 -1
  41. data/performance.rb +109 -34
  42. data/plugins/can_has_sphinx/LICENSE +23 -0
  43. data/plugins/can_has_sphinx/README +4 -0
  44. data/plugins/can_has_sphinx/REVISION +1 -0
  45. data/plugins/can_has_sphinx/Rakefile +22 -0
  46. data/plugins/can_has_sphinx/init.rb +1 -0
  47. data/plugins/can_has_sphinx/install.rb +1 -0
  48. data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +123 -0
  49. data/plugins/can_has_sphinx/lib/sphinx.rb +460 -0
  50. data/plugins/can_has_sphinx/scripts/sphinx.sh +47 -0
  51. data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +41 -0
  52. data/plugins/dataobjects/REVISION +1 -0
  53. data/plugins/dataobjects/Rakefile +7 -0
  54. data/plugins/dataobjects/do.rb +246 -0
  55. data/plugins/dataobjects/do_mysql.rb +179 -0
  56. data/plugins/dataobjects/do_postgres.rb +181 -0
  57. data/plugins/dataobjects/do_sqlite3.rb +153 -0
  58. data/plugins/dataobjects/spec/do_spec.rb +150 -0
  59. data/plugins/dataobjects/spec/spec_helper.rb +81 -0
  60. data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
  61. data/plugins/dataobjects/swig_mysql/extconf.rb +33 -0
  62. data/plugins/dataobjects/swig_mysql/mysql_c.c +18800 -0
  63. data/plugins/dataobjects/swig_mysql/mysql_c.i +8 -0
  64. data/plugins/dataobjects/swig_mysql/mysql_supp.i +46 -0
  65. data/plugins/dataobjects/swig_postgres/Makefile +146 -0
  66. data/plugins/dataobjects/swig_postgres/extconf.rb +29 -0
  67. data/plugins/dataobjects/swig_postgres/postgres_c.bundle +0 -0
  68. data/plugins/dataobjects/swig_postgres/postgres_c.c +8185 -0
  69. data/plugins/dataobjects/swig_postgres/postgres_c.i +73 -0
  70. data/plugins/dataobjects/swig_sqlite/db +0 -0
  71. data/plugins/dataobjects/swig_sqlite/extconf.rb +9 -0
  72. data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +4725 -0
  73. data/plugins/dataobjects/swig_sqlite/sqlite_c.i +168 -0
  74. data/rakefile.rb +45 -23
  75. data/spec/acts_as_tree_spec.rb +39 -0
  76. data/spec/associations_spec.rb +220 -0
  77. data/spec/attributes_spec.rb +15 -0
  78. data/spec/base_spec.rb +44 -0
  79. data/spec/callbacks_spec.rb +45 -0
  80. data/spec/can_has_sphinx.rb +6 -0
  81. data/spec/coersion_spec.rb +34 -0
  82. data/spec/conditions_spec.rb +49 -0
  83. data/spec/conversions_to_yaml_spec.rb +17 -0
  84. data/spec/count_command_spec.rb +11 -0
  85. data/spec/delete_command_spec.rb +1 -1
  86. data/spec/embedded_value_spec.rb +23 -0
  87. data/spec/fixtures/animals_exhibits.yaml +2 -0
  88. data/spec/fixtures/people.yaml +18 -1
  89. data/spec/{legacy.rb → legacy_spec.rb} +3 -3
  90. data/spec/load_command_spec.rb +157 -20
  91. data/spec/magic_columns_spec.rb +9 -0
  92. data/spec/mock_adapter.rb +20 -0
  93. data/spec/models/animal.rb +1 -1
  94. data/spec/models/animals_exhibit.rb +6 -0
  95. data/spec/models/exhibit.rb +2 -0
  96. data/spec/models/person.rb +26 -1
  97. data/spec/models/project.rb +19 -0
  98. data/spec/models/sales_person.rb +1 -0
  99. data/spec/models/section.rb +6 -0
  100. data/spec/models/zoo.rb +3 -1
  101. data/spec/query_spec.rb +9 -0
  102. data/spec/save_command_spec.rb +65 -1
  103. data/spec/schema_spec.rb +89 -0
  104. data/spec/single_table_inheritance_spec.rb +27 -0
  105. data/spec/spec_helper.rb +9 -55
  106. data/spec/{symbolic_operators.rb → symbolic_operators_spec.rb} +9 -5
  107. data/spec/{validates_confirmation_of.rb → validates_confirmation_of_spec.rb} +4 -3
  108. data/spec/{validates_format_of.rb → validates_format_of_spec.rb} +5 -4
  109. data/spec/{validates_length_of.rb → validates_length_of_spec.rb} +8 -7
  110. data/spec/{validates_uniqueness_of.rb → validates_uniqueness_of_spec.rb} +7 -10
  111. data/spec/{validations.rb → validations_spec.rb} +24 -6
  112. data/tasks/drivers.rb +20 -0
  113. data/tasks/fixtures.rb +42 -0
  114. metadata +181 -42
  115. data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +0 -140
  116. data/lib/data_mapper/adapters/sql/commands/delete_command.rb +0 -113
  117. data/lib/data_mapper/adapters/sql/commands/save_command.rb +0 -141
  118. data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +0 -33
  119. data/lib/data_mapper/adapters/sql_adapter.rb +0 -163
  120. data/lib/data_mapper/associations/advanced_has_many_association.rb +0 -55
  121. data/lib/data_mapper/support/blank_slate.rb +0 -3
  122. data/lib/data_mapper/support/proc.rb +0 -69
  123. data/lib/data_mapper/support/struct.rb +0 -26
  124. data/lib/data_mapper/unit_of_work.rb +0 -38
  125. data/spec/basic_finder.rb +0 -67
  126. data/spec/belongs_to.rb +0 -47
  127. data/spec/has_and_belongs_to_many.rb +0 -25
  128. data/spec/has_many.rb +0 -34
  129. data/spec/new_record.rb +0 -24
  130. data/spec/sub_select.rb +0 -16
  131. data/spec/support/string_spec.rb +0 -7
data/CHANGELOG CHANGED
@@ -30,3 +30,68 @@
30
30
  * Added DataMapper::Support::Struct for increased Session#query performance
31
31
  * Added AdvancedHasManyAssociation (preview status)
32
32
  * Added benchmarks comparing ActiveRecord::Base::find_by_sql with Session#query
33
+
34
+ -- 0.2.0
35
+ * AdvancedHasManyAssociation now functional for fetches
36
+ * AdvancedHasManyAssociation renamed to HasNAssociation
37
+ * HasManyAssociation refactored to use HasNAssociation superclass
38
+ * Slight spec tweaks to accomodate the updates
39
+ * HasOneAssociation refactored to use HasNAssociation superclass
40
+ * Added HasAndBelongsToManyAssociation, using HasNAssociation as a basis; Need to add corresponding SQL generation code in AdvancedLoadCommand
41
+ * Added spec for habtm query generation
42
+ * HasNAssociation#foreign_key returns a DataMapper::Adapters::Sql::Mappings::Column instance instead of a raw String now
43
+ * Added table, association, association_table and to_sql methods to HasNAssociation
44
+ * Added associations_spec.rb
45
+ * Added a forced table-recreation to spec_helper.rb so the tests could run with a clean version of the database, including any new columns added to the models
46
+ * Added HasAndBelongsToManyAssociation#to_sql (all current specs pass now!)
47
+ * Minor tweaks to Callbacks
48
+ * Added CallbacksHelper to declare class-method ::callbacks on DataMapper::Base
49
+ * Implemented before_validate and after_validate hooks in ValidationHelper
50
+ * Minor documentation additions in callbacks.rb
51
+ * Added callbacks_spec
52
+ * Moved class-method declarations for built-in callbacks to the callbacks helper instead of DataMapper::Base
53
+ * Renamed :before/after_validate callback to :before/after_validation to match ActiveRecord
54
+ * Callbacks#add now accepts a Symbol which maps a callback to a method call on the targetted instance, also added a spec to verify this behavior
55
+ * Documented callbacks.rb
56
+ * Added DataMapper::Associations::Reference class
57
+ * Documented DataMapper::Associations::Reference class
58
+ * Upgraded BelongsToAssociation to new style
59
+ * Added AssociationsSet to handle simple "last-in" for association bindings
60
+ * Fixed extra spec loading
61
+ * Added *Association#columns
62
+ * Some refactoring in AdvancedLoadCommand regarding :include options
63
+ * Added support for class-less Mappings::Table instances, with just a string name
64
+ * HasAndBelongsToManyAssociation#join_table #left_foreign_key and #right_foreign_key reference actual Table or Column objects now
65
+ * Added :shallow_include option for HABTM joins in AdvancedLoadCommand and corresponding spec
66
+ * Added Commands::AdvancedConditions
67
+ * Added ORDER, LIMIT, OFFSET and WHERE support to AdvancedLoadCommand
68
+ * Renamed spec/has_many.rb to spec/has_many_spec.rb
69
+ * Tweaked the loading of has_many relationships; big performance boost; got rid of an extra query
70
+ * Added EmbeddedValue support, and accompanying spec
71
+ * Fleshed out AdvancedConditions a bit; added conditions_spec.rb
72
+ * Added more AdvancedConditions specs
73
+ * Added Loader to handle multi-instanced rows
74
+ * AdvancedLoadCommand replaced LoadCommand; down to 3 failing specs
75
+ * All specs pass
76
+ * Added :intercept_load finder option and accompanying spec
77
+ * Modified :intercept_load block signature to |instance,columns,row|
78
+ * HasAndBelongsToMany works, all specs pass
79
+ * Fixed a couple bugs with keys; Added DataMapper::Base#key= method
80
+ * Made DataMapper::Base#lazy_load! a little more flexible
81
+ * Removed LoadCommand overwrites from MysqlAdapter
82
+ * Default Database#single_threaded mode is true now
83
+ * Removed MysqlAdapter#initialize, which only served to setup the connections, moved to SqlAdapter
84
+ * Added SqlAdapter#create_connection and SqlAdapter#close_connection abstract methods
85
+ * Added MysqlAdapter#create_connection and MysqlAdapter#close_connection concrete methods
86
+ * Made SqlAdapter#connection a concrete method (instead of abstract), with support for single_threaded operation
87
+ * Database#setup now takes a Hash of options instead of a block-initializer
88
+ * Validation chaining should work for all association types
89
+ * Save chaining should work for has_many associations
90
+ * Added benchmarks for in-session performance to performance.rb
91
+ * Removed block conditions; They're slower and don't offer any real advantages
92
+ * Removed DeleteCommand
93
+ * Removed SaveCommand
94
+ * Removed TableExistsCommand
95
+ * Session renamed to Context
96
+ * Most command implementations moved to methods in SqlAdapter
97
+ * Removed UnitOfWork module, instead moving a slightly refactored implementation into Base
data/README CHANGED
@@ -1,5 +1,197 @@
1
- Start out with example.rb and go from there if you want to try it out live.
1
+ = DataMapper
2
2
 
3
+ DataMapper is an Object Relational Mapper written in Ruby. The goal is to create an ORM which is fast, thread-safe and feature rich.
4
+
5
+ == Why you should use DataMapper
6
+
7
+ === Speed
8
+
9
+ DataMapper combines tried and true principles from Martin Fowler's design patterns with a pure ruby implementation,
10
+ creating not only beautiful syntax, but a huge speed up from other popular ORMs.
11
+
12
+ Where other ORMs have failed you before, DataMapper strives to make up for this gap.
13
+
14
+ If this has piqued your interest, look below and learn how to get started.
15
+
16
+ If you're looking for cold hard numbers, take a gander at the PERFORMANCE file.
17
+ You'll find the latest performance stats under "Current Performance".
18
+
19
+
20
+ Most tests are run on a 2.16Ghz Core2Duo iMac.
21
+ Asterisk (*) indicates test run on 2.0Ghz Core2Duo MacBook.
22
+
23
+ === Open Development
24
+
25
+ Found a bug or want a feature? Tired of dealing with the bureaucracy that other ORM maintainers force upon you?
26
+
27
+ The community surrounding DataMapper is open and friendly. Contributions of any kind are welcome,
28
+ and the founder and maintainer of the project can be easily reached by using the fairly active
29
+ mailing list (http://groups.google.com/group/datamapper) or by jumping in to the <tt>datamapper</tt>
30
+ channel on irc.freenode.net.
31
+
32
+ === Thread-Safe
33
+
34
+ Thread safety is a critical topic in any production software, and especially so with the DataMapper.
35
+ The maintainers have dedicated much of their time to ensuring that the DataMapper is thread safe thus far,
36
+ and will continue to do as much to ensure it stays that way.
37
+
38
+ === Hacker Friendly
39
+
40
+ One of the most frustrating problems with other ORMs is the painstaking time it takes
41
+ to understand and traverse the code-base.
42
+
43
+ DataMapper aims to be as lightweight as possible, keeping
44
+ the code-base clean and uncluttered. Never be afraid to crack open the subversion trunk again!
45
+
46
+
47
+ == Getting Started
48
+
49
+ === Install DataMapper
50
+ There are two simple options for getting started with DataMapper.
51
+
52
+ If you'd like to use SVN and check out the bleeding edge version of the project,
53
+ execute the following command in your terminal:
54
+
55
+
56
+ svn co http://datamapper.rubyforge.org/svn/trunk/ data_mapper
57
+
58
+ After checking out the trunk, point your application to the trunk/lib folder and require it.
59
+
60
+ If you'd like to just <i>use</i> datamapper and don't plan on looking at the source code or want bleeding edge features,
61
+ execute this instead:
62
+
63
+ gem install datamapper
64
+
65
+ ==== QuickStart
66
+ If you want to find out how to use DataMapper in your existing application, jump to "Require it in your application".
67
+
68
+ If you'd like to get started right away and play with the syntax of DataMapper, and you're using MySQL as your database,
69
+ create a new database called:
70
+ data_mapper_1
71
+
72
+ Then drop into the trunk directory, and execute:
73
+ rake
74
+
75
+ That will setup your database. From there, execute:
76
+ ruby example.rb
77
+
78
+ This will drop you into an IRB session, where you can further play with the syntax. Try out the intuitive finders:
79
+ Animal[0]
80
+ Animal.all
81
+ Zoo.first(:name => 'Galveston')
82
+ Zoo.find(:first, :conditions => ['name = ?', 'Galveston'])
83
+
84
+ === Require it in your application
85
+
86
+ require 'rubygems'
87
+ require 'data_mapper'
88
+
89
+ === Specify a Database Connection
90
+
91
+ Datamapper has Merb and Rails users in mind when setting up. If you've already setup a Merb or
92
+ Ruby on Rails project, and have a database.yml, DataMapper should pick it up automatically.
93
+
94
+ If you'd like to set the database connection manually before using it, do something like this:
95
+ DataMapper::Database.setup({
96
+ :adapter => 'mysql'
97
+ :host => 'localhost'
98
+ :username => 'root'
99
+ :password => 'R00tPaswooooord'
100
+ :database => 'selecta_development'
101
+ })
102
+
103
+ The currently supported databases are:
104
+ PostgreSQL:: (postgresql adaptor)
105
+ MySQL:: (mysql adaptor)
106
+ SQLite3:: (sqlite3 adaptor)
107
+
108
+ === Define Your Models
109
+
110
+ Defining your models requires a few steps.
111
+
112
+ * Inherit your class from DataMapper::Base
113
+ * Define your properties you wish to access from the database
114
+ * Define any relationships (optional)
115
+
116
+ Unlike many other ORMs, DataMapper requires that you define which fields in the database
117
+ you'd like to make available to your models as properties. There are a few reasons for this,
118
+ which are too numerous to go into here.
119
+
120
+ Your models might end up looking something like this:
121
+
122
+ class Animal < DataMapper::Base
123
+ property :name, :string
124
+ property :notes, :text, :lazy => true
125
+
126
+ has_one :favourite_fruit, :class => 'Fruit', :foreign_key => 'devourer_id'
127
+ has_and_belongs_to_many :exhibits
128
+ end
129
+
130
+ ==== Lazy Attributes
131
+
132
+ Lazy attributes are one of the many speed enhancing features in DataMapper.
133
+
134
+ Properties that are given the lazy attribute will not be loaded until they are accessed by your code.
135
+
136
+ So if you were to load a set of database records from your database, and only used the lazy property
137
+ of those records occasionally, your memory signature will essentially stay much smaller, while still
138
+ easily allowing you to gain access to those attributes when you need them.
139
+
140
+ For example, if you were to load all of the Animals using the class above, and were to inspect the set
141
+ of returned data, you'd notice that all of the notes fields were <b>nil</b>. If you were to do something
142
+ like the following:
143
+
144
+ animals = Animals.all
145
+ animals.inspect
146
+
147
+ You'd notice the <b>nil</b> fields immediately.
148
+
149
+ If you were to do something like the following:
150
+ animals.first.notes
151
+ animals.inspect
152
+
153
+ You'd notice that ALL of the notes fields in your set were loaded into memory.
154
+
155
+ The astute rubyist will immediately wonder if this is possible on associations, and indeed it is!
156
+ This inevitably avoids the 1+N query problems that have so plagued us in the past. It allows us to
157
+ develop in an intuitive manner, so that if we executed a loop:
158
+
159
+ animals.each do |animal|
160
+ #The next line crafts a query to fetch ALL of this
161
+ #set's favorite_fruit attributes
162
+ puts animal.favorite_fruit
163
+ end
164
+
165
+ Only two queries hit our database. All with the automagical power of DataMapper!
166
+
167
+ === Associations
168
+
169
+ DataMapper's associations are exactly like the other ORMs out there. Some association examples are found below:
170
+
171
+ * belongs_to :model
172
+ * has_one :model
173
+ * has_many :model
174
+ * has_and_belongs_to_many :model
175
+
176
+ You can also set the class and foreign_keys for each association if you need to override the default naming scheme.
177
+
178
+ == AutoMigrations
179
+
180
+ With DataMapper, there's no need to constantly create migration after monotonous migration during your initial development.
181
+
182
+ Once you've got your models to a point where you'd like a table associated with them, simply execute the following:
183
+
184
+ database.save(ModelName)
185
+
186
+ This will generate the table structure for your model automatically.
187
+
188
+ You can also execute the following to generate ALL of your models' tables:
189
+
190
+ DataMapper::Base.auto_migrate!
191
+
192
+ === NOTE
193
+ Both of these methods are DESTRUCTIVE. If you are working in anything other than a pre-production environment,
194
+ stay far away from these methods!
3
195
 
4
196
  == Conventions
5
197
 
data/do_performance.rb ADDED
@@ -0,0 +1,153 @@
1
+ require 'benchmark'
2
+ require 'lib/data_mapper'
3
+
4
+ DataMapper::Database.setup({
5
+ :adapter => 'do_mysql',
6
+ :database => 'data_mapper_1',
7
+ :username => 'root'
8
+ })
9
+
10
+ class DMAnimal < DataMapper::Base
11
+ set_table_name 'animals'
12
+ property :name, :string
13
+ property :notes, :string
14
+ end
15
+
16
+ class DMPerson < DataMapper::Base
17
+ set_table_name 'people'
18
+ property :name, :string
19
+ property :age, :integer
20
+ property :occupation, :string
21
+ property :notes, :text
22
+ property :street, :string
23
+ property :city, :string
24
+ property :state, :string, :size => 2
25
+ property :zip_code, :string, :size => 10
26
+ end
27
+
28
+ class Exhibit < DataMapper::Base
29
+ property :name, :string
30
+ belongs_to :zoo
31
+ end
32
+
33
+ class Zoo < DataMapper::Base
34
+ property :name, :string
35
+ has_many :exhibits
36
+ end
37
+
38
+ N = (ENV['N'] || 1000).to_i
39
+
40
+ # 4.times do
41
+ # [DMAnimal, Zoo, Exhibit].each do |klass|
42
+ # klass.all.each do |instance|
43
+ # klass.create(instance.attributes.reject { |k,v| k == :id })
44
+ # end
45
+ # end
46
+ # end
47
+
48
+ Benchmark::send(ENV['BM'] || :bmbm, 40) do |x|
49
+
50
+ x.report('DataMapper:id') do
51
+ N.times { DMAnimal[1] }
52
+ end
53
+
54
+ x.report('DataMapper:id:in-session') do
55
+ database do
56
+ N.times { DMAnimal[1] }
57
+ end
58
+ end
59
+
60
+ x.report('DataMapper:all') do
61
+ N.times { DMAnimal.all }
62
+ end
63
+
64
+ x.report('DataMapper:all:in-session') do
65
+ database do
66
+ N.times { DMAnimal.all }
67
+ end
68
+ end
69
+
70
+ x.report('DataMapper:conditions:short') do
71
+ N.times { Zoo[:name => 'Galveston'] }
72
+ end
73
+
74
+ x.report('DataMapper:conditions:short:in-session') do
75
+ database do
76
+ N.times { Zoo[:name => 'Galveston'] }
77
+ end
78
+ end
79
+
80
+ x.report('DataMapper:conditions:long') do
81
+ N.times { Zoo.find(:first, :conditions => ['name = ?', 'Galveston']) }
82
+ end
83
+
84
+ x.report('DataMapper:conditions:long:in-session') do
85
+ database do
86
+ N.times { Zoo.find(:first, :conditions => ['name = ?', 'Galveston']) }
87
+ end
88
+ end
89
+
90
+ people = [
91
+ ['Sam', 29, 'Programmer', 'A slow text field'],
92
+ ['Amy', 28, 'Business Analyst Manager', 'A slow text field'],
93
+ ['Scott', 25, 'Programmer', 'A slow text field'],
94
+ ['Josh', 23, 'Supervisor', 'A slow text field'],
95
+ ['Bob', 40, 'Peon', 'A slow text field']
96
+ ]
97
+
98
+ DMPerson.truncate!
99
+
100
+ x.report('DataMapper:insert') do
101
+ N.times do
102
+ people.each do |a|
103
+ DMPerson::create(:name => a[0], :age => a[1], :occupation => a[2], :notes => a[3])
104
+ end
105
+ end
106
+ end
107
+
108
+ x.report('DataMapper:update') do
109
+ N.times do
110
+ bob = DMAnimal.first(:name => 'Elephant')
111
+ bob.notes = 'Updated by DataMapper'
112
+ bob.save
113
+ end
114
+ end
115
+
116
+ x.report('DataMapper:associations') do
117
+ N.times do
118
+ Zoo.all.each { |zoo| zoo.exhibits.entries }
119
+ end
120
+ end
121
+
122
+ x.report('DataMapper:associations:in-session') do
123
+ database do
124
+ N.times do
125
+ Zoo.all.each { |zoo| zoo.exhibits.entries }
126
+ end
127
+ end
128
+ end
129
+
130
+ x.report('DataMapper:find_by_sql') do
131
+ N.times do
132
+ database.query("SELECT * FROM zoos")
133
+ end
134
+ end
135
+
136
+ x.report('DataMapper:accessors') do
137
+ person = DMPerson.first
138
+
139
+ N.times do
140
+ <<-VCARD
141
+ #{person.name} (#{person.age})
142
+ #{person.occupation}
143
+
144
+ #{person.street}
145
+ #{person.city}, #{person.state} #{person.zip_code}
146
+
147
+ #{person.notes}
148
+ VCARD
149
+ end
150
+ end
151
+
152
+
153
+ end
data/environment.rb ADDED
@@ -0,0 +1,45 @@
1
+ # Require the DataMapper, and a Mock Adapter.
2
+ require File.dirname(__FILE__) + '/lib/data_mapper'
3
+ require File.dirname(__FILE__) + '/spec/mock_adapter'
4
+
5
+ adapter = ENV['ADAPTER'] || 'sqlite3'
6
+
7
+ configuration_options = {
8
+ :adapter => adapter,
9
+ :database => (ENV['DATABASE'] || 'data_mapper_1').dup,
10
+ :single_threaded => true
11
+ }
12
+
13
+ # Prepare the log path, and remove the existing spec.log
14
+ require 'fileutils'
15
+
16
+ if ENV['LOG_NAME']
17
+ FileUtils::mkdir_p(File.dirname(__FILE__) + '/log')
18
+ log_path = File.dirname(__FILE__) + "/log/#{ENV['LOG_NAME']}.log"
19
+ FileUtils::rm log_path if File.exists?(log_path)
20
+
21
+ configuration_options.merge!(:log_stream => log_path, :log_level => Logger::DEBUG)
22
+ end
23
+
24
+ case adapter
25
+ when 'postgresql' then
26
+ configuration_options[:username] = ENV['USERNAME'] || 'postgres'
27
+ when 'mysql' then
28
+ configuration_options[:username] = 'root'
29
+ when 'sqlite3' then
30
+ unless configuration_options[:database] == ':memory:'
31
+ configuration_options[:database] << '.db'
32
+ end
33
+ end
34
+
35
+ load_models = lambda do
36
+ Dir[File.dirname(__FILE__) + '/spec/models/*.rb'].sort.each { |path| load path }
37
+ end
38
+
39
+ DataMapper::Database.setup(configuration_options)
40
+ DataMapper::Database.setup(:mock, :adapter => MockAdapter)
41
+
42
+ [:default, :mock].each { |name| database(name) { load_models.call } }
43
+
44
+ # Reset the test database.
45
+ DataMapper::Base.auto_migrate!