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.
- data/CHANGELOG +65 -0
- data/README +193 -1
- data/do_performance.rb +153 -0
- data/environment.rb +45 -0
- data/example.rb +119 -22
- data/lib/data_mapper.rb +36 -16
- data/lib/data_mapper/adapters/abstract_adapter.rb +8 -0
- data/lib/data_mapper/adapters/data_object_adapter.rb +360 -0
- data/lib/data_mapper/adapters/mysql_adapter.rb +30 -179
- data/lib/data_mapper/adapters/postgresql_adapter.rb +90 -199
- data/lib/data_mapper/adapters/sql/coersion.rb +32 -3
- data/lib/data_mapper/adapters/sql/commands/conditions.rb +97 -128
- data/lib/data_mapper/adapters/sql/commands/load_command.rb +234 -231
- data/lib/data_mapper/adapters/sql/commands/loader.rb +99 -0
- data/lib/data_mapper/adapters/sql/mappings/associations_set.rb +30 -0
- data/lib/data_mapper/adapters/sql/mappings/column.rb +68 -6
- data/lib/data_mapper/adapters/sql/mappings/schema.rb +6 -3
- data/lib/data_mapper/adapters/sql/mappings/table.rb +71 -42
- data/lib/data_mapper/adapters/sql/quoting.rb +8 -2
- data/lib/data_mapper/adapters/sqlite3_adapter.rb +32 -201
- data/lib/data_mapper/associations.rb +21 -7
- data/lib/data_mapper/associations/belongs_to_association.rb +96 -80
- data/lib/data_mapper/associations/has_and_belongs_to_many_association.rb +158 -67
- data/lib/data_mapper/associations/has_many_association.rb +96 -78
- data/lib/data_mapper/associations/has_n_association.rb +64 -0
- data/lib/data_mapper/associations/has_one_association.rb +49 -79
- data/lib/data_mapper/associations/reference.rb +47 -0
- data/lib/data_mapper/base.rb +216 -50
- data/lib/data_mapper/callbacks.rb +71 -24
- data/lib/data_mapper/{session.rb → context.rb} +20 -8
- data/lib/data_mapper/database.rb +176 -45
- data/lib/data_mapper/embedded_value.rb +65 -0
- data/lib/data_mapper/identity_map.rb +12 -4
- data/lib/data_mapper/support/active_record_impersonation.rb +12 -8
- data/lib/data_mapper/support/enumerable.rb +8 -0
- data/lib/data_mapper/support/serialization.rb +13 -0
- data/lib/data_mapper/support/string.rb +1 -12
- data/lib/data_mapper/support/symbol.rb +3 -0
- data/lib/data_mapper/validations/unique_validator.rb +1 -2
- data/lib/data_mapper/validations/validation_helper.rb +18 -1
- data/performance.rb +109 -34
- data/plugins/can_has_sphinx/LICENSE +23 -0
- data/plugins/can_has_sphinx/README +4 -0
- data/plugins/can_has_sphinx/REVISION +1 -0
- data/plugins/can_has_sphinx/Rakefile +22 -0
- data/plugins/can_has_sphinx/init.rb +1 -0
- data/plugins/can_has_sphinx/install.rb +1 -0
- data/plugins/can_has_sphinx/lib/acts_as_sphinx.rb +123 -0
- data/plugins/can_has_sphinx/lib/sphinx.rb +460 -0
- data/plugins/can_has_sphinx/scripts/sphinx.sh +47 -0
- data/plugins/can_has_sphinx/tasks/acts_as_sphinx_tasks.rake +41 -0
- data/plugins/dataobjects/REVISION +1 -0
- data/plugins/dataobjects/Rakefile +7 -0
- data/plugins/dataobjects/do.rb +246 -0
- data/plugins/dataobjects/do_mysql.rb +179 -0
- data/plugins/dataobjects/do_postgres.rb +181 -0
- data/plugins/dataobjects/do_sqlite3.rb +153 -0
- data/plugins/dataobjects/spec/do_spec.rb +150 -0
- data/plugins/dataobjects/spec/spec_helper.rb +81 -0
- data/plugins/dataobjects/swig_mysql/do_mysql.bundle +0 -0
- data/plugins/dataobjects/swig_mysql/extconf.rb +33 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.c +18800 -0
- data/plugins/dataobjects/swig_mysql/mysql_c.i +8 -0
- data/plugins/dataobjects/swig_mysql/mysql_supp.i +46 -0
- data/plugins/dataobjects/swig_postgres/Makefile +146 -0
- data/plugins/dataobjects/swig_postgres/extconf.rb +29 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.bundle +0 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.c +8185 -0
- data/plugins/dataobjects/swig_postgres/postgres_c.i +73 -0
- data/plugins/dataobjects/swig_sqlite/db +0 -0
- data/plugins/dataobjects/swig_sqlite/extconf.rb +9 -0
- data/plugins/dataobjects/swig_sqlite/sqlite3_c.c +4725 -0
- data/plugins/dataobjects/swig_sqlite/sqlite_c.i +168 -0
- data/rakefile.rb +45 -23
- data/spec/acts_as_tree_spec.rb +39 -0
- data/spec/associations_spec.rb +220 -0
- data/spec/attributes_spec.rb +15 -0
- data/spec/base_spec.rb +44 -0
- data/spec/callbacks_spec.rb +45 -0
- data/spec/can_has_sphinx.rb +6 -0
- data/spec/coersion_spec.rb +34 -0
- data/spec/conditions_spec.rb +49 -0
- data/spec/conversions_to_yaml_spec.rb +17 -0
- data/spec/count_command_spec.rb +11 -0
- data/spec/delete_command_spec.rb +1 -1
- data/spec/embedded_value_spec.rb +23 -0
- data/spec/fixtures/animals_exhibits.yaml +2 -0
- data/spec/fixtures/people.yaml +18 -1
- data/spec/{legacy.rb → legacy_spec.rb} +3 -3
- data/spec/load_command_spec.rb +157 -20
- data/spec/magic_columns_spec.rb +9 -0
- data/spec/mock_adapter.rb +20 -0
- data/spec/models/animal.rb +1 -1
- data/spec/models/animals_exhibit.rb +6 -0
- data/spec/models/exhibit.rb +2 -0
- data/spec/models/person.rb +26 -1
- data/spec/models/project.rb +19 -0
- data/spec/models/sales_person.rb +1 -0
- data/spec/models/section.rb +6 -0
- data/spec/models/zoo.rb +3 -1
- data/spec/query_spec.rb +9 -0
- data/spec/save_command_spec.rb +65 -1
- data/spec/schema_spec.rb +89 -0
- data/spec/single_table_inheritance_spec.rb +27 -0
- data/spec/spec_helper.rb +9 -55
- data/spec/{symbolic_operators.rb → symbolic_operators_spec.rb} +9 -5
- data/spec/{validates_confirmation_of.rb → validates_confirmation_of_spec.rb} +4 -3
- data/spec/{validates_format_of.rb → validates_format_of_spec.rb} +5 -4
- data/spec/{validates_length_of.rb → validates_length_of_spec.rb} +8 -7
- data/spec/{validates_uniqueness_of.rb → validates_uniqueness_of_spec.rb} +7 -10
- data/spec/{validations.rb → validations_spec.rb} +24 -6
- data/tasks/drivers.rb +20 -0
- data/tasks/fixtures.rb +42 -0
- metadata +181 -42
- data/lib/data_mapper/adapters/sql/commands/advanced_load_command.rb +0 -140
- data/lib/data_mapper/adapters/sql/commands/delete_command.rb +0 -113
- data/lib/data_mapper/adapters/sql/commands/save_command.rb +0 -141
- data/lib/data_mapper/adapters/sql/commands/table_exists_command.rb +0 -33
- data/lib/data_mapper/adapters/sql_adapter.rb +0 -163
- data/lib/data_mapper/associations/advanced_has_many_association.rb +0 -55
- data/lib/data_mapper/support/blank_slate.rb +0 -3
- data/lib/data_mapper/support/proc.rb +0 -69
- data/lib/data_mapper/support/struct.rb +0 -26
- data/lib/data_mapper/unit_of_work.rb +0 -38
- data/spec/basic_finder.rb +0 -67
- data/spec/belongs_to.rb +0 -47
- data/spec/has_and_belongs_to_many.rb +0 -25
- data/spec/has_many.rb +0 -34
- data/spec/new_record.rb +0 -24
- data/spec/sub_select.rb +0 -16
- 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
|
-
|
|
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!
|