datamapper 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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!