dm-core 0.9.2 → 0.9.3

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 (84) hide show
  1. data/.autotest +26 -0
  2. data/{CHANGELOG → History.txt} +78 -77
  3. data/Manifest.txt +123 -0
  4. data/{README → README.txt} +0 -0
  5. data/Rakefile +29 -0
  6. data/SPECS +63 -0
  7. data/TODO +1 -0
  8. data/lib/dm-core.rb +6 -1
  9. data/lib/dm-core/adapters/data_objects_adapter.rb +29 -32
  10. data/lib/dm-core/adapters/mysql_adapter.rb +1 -1
  11. data/lib/dm-core/adapters/postgres_adapter.rb +1 -1
  12. data/lib/dm-core/adapters/sqlite3_adapter.rb +2 -2
  13. data/lib/dm-core/associations.rb +26 -0
  14. data/lib/dm-core/associations/many_to_many.rb +34 -25
  15. data/lib/dm-core/associations/many_to_one.rb +4 -4
  16. data/lib/dm-core/associations/one_to_many.rb +48 -13
  17. data/lib/dm-core/associations/one_to_one.rb +4 -4
  18. data/lib/dm-core/associations/relationship.rb +144 -42
  19. data/lib/dm-core/associations/relationship_chain.rb +31 -24
  20. data/lib/dm-core/auto_migrations.rb +0 -4
  21. data/lib/dm-core/collection.rb +40 -7
  22. data/lib/dm-core/dependency_queue.rb +31 -0
  23. data/lib/dm-core/hook.rb +2 -2
  24. data/lib/dm-core/is.rb +2 -2
  25. data/lib/dm-core/logger.rb +10 -10
  26. data/lib/dm-core/model.rb +94 -41
  27. data/lib/dm-core/property.rb +72 -41
  28. data/lib/dm-core/property_set.rb +8 -14
  29. data/lib/dm-core/query.rb +34 -9
  30. data/lib/dm-core/repository.rb +0 -0
  31. data/lib/dm-core/resource.rb +13 -13
  32. data/lib/dm-core/scope.rb +25 -2
  33. data/lib/dm-core/type.rb +3 -3
  34. data/lib/dm-core/types/discriminator.rb +10 -8
  35. data/lib/dm-core/types/object.rb +4 -0
  36. data/lib/dm-core/types/paranoid_boolean.rb +15 -4
  37. data/lib/dm-core/types/paranoid_datetime.rb +15 -4
  38. data/lib/dm-core/version.rb +3 -0
  39. data/script/all +5 -0
  40. data/script/performance.rb +191 -0
  41. data/script/profile.rb +86 -0
  42. data/spec/integration/association_spec.rb +288 -204
  43. data/spec/integration/association_through_spec.rb +9 -3
  44. data/spec/integration/associations/many_to_many_spec.rb +97 -31
  45. data/spec/integration/associations/many_to_one_spec.rb +41 -6
  46. data/spec/integration/associations/one_to_many_spec.rb +18 -2
  47. data/spec/integration/auto_migrations_spec.rb +0 -0
  48. data/spec/integration/collection_spec.rb +89 -42
  49. data/spec/integration/dependency_queue_spec.rb +58 -0
  50. data/spec/integration/model_spec.rb +67 -8
  51. data/spec/integration/postgres_adapter_spec.rb +19 -20
  52. data/spec/integration/property_spec.rb +17 -8
  53. data/spec/integration/query_spec.rb +273 -191
  54. data/spec/integration/resource_spec.rb +108 -10
  55. data/spec/integration/strategic_eager_loading_spec.rb +138 -0
  56. data/spec/integration/transaction_spec.rb +3 -3
  57. data/spec/integration/type_spec.rb +121 -0
  58. data/spec/lib/logging_helper.rb +18 -0
  59. data/spec/lib/model_loader.rb +91 -0
  60. data/spec/lib/publicize_methods.rb +28 -0
  61. data/spec/models/vehicles.rb +34 -0
  62. data/spec/models/zoo.rb +48 -0
  63. data/spec/spec.opts +3 -0
  64. data/spec/spec_helper.rb +25 -62
  65. data/spec/unit/adapters/data_objects_adapter_spec.rb +1 -0
  66. data/spec/unit/associations/many_to_many_spec.rb +3 -0
  67. data/spec/unit/associations/many_to_one_spec.rb +9 -1
  68. data/spec/unit/associations/one_to_many_spec.rb +12 -4
  69. data/spec/unit/associations/relationship_spec.rb +19 -15
  70. data/spec/unit/associations_spec.rb +37 -0
  71. data/spec/unit/collection_spec.rb +8 -0
  72. data/spec/unit/data_mapper_spec.rb +14 -0
  73. data/spec/unit/model_spec.rb +2 -2
  74. data/spec/unit/property_set_spec.rb +0 -13
  75. data/spec/unit/property_spec.rb +92 -21
  76. data/spec/unit/query_spec.rb +49 -4
  77. data/spec/unit/resource_spec.rb +122 -60
  78. data/spec/unit/scope_spec.rb +11 -0
  79. data/tasks/ci.rb +68 -0
  80. data/tasks/dm.rb +63 -0
  81. data/tasks/doc.rb +20 -0
  82. data/tasks/hoe.rb +38 -0
  83. data/tasks/install.rb +20 -0
  84. metadata +63 -22
data/.autotest ADDED
@@ -0,0 +1,26 @@
1
+ Autotest.add_hook :initialize do |at|
2
+ ignore = %w[ .git burn www log plugins script tasks bin CHANGELOG FAQ MIT-LICENSE PERFORMANCE QUICKLINKS README ]
3
+
4
+ unless ENV['AUTOTEST'] == 'integration'
5
+ ignore << 'spec/integration'
6
+ end
7
+
8
+ ignore.each do |exception|
9
+ at.add_exception(exception)
10
+ end
11
+
12
+ at.clear_mappings
13
+
14
+ at.add_mapping(%r{^spec/.+_spec\.rb$}) do |filename,_|
15
+ filename
16
+ end
17
+
18
+ at.add_mapping(%r{^lib/data_mapper/(.+)\.rb$}) do |_,match|
19
+ [ "spec/unit/#{match[1]}_spec.rb" ] +
20
+ at.files_matching(%r{^spec/integration/.+_spec\.rb$})
21
+ end
22
+
23
+ at.add_mapping(%r{^spec/spec_helper\.rb$}) do
24
+ at.files_matching(%r{^spec/.+_spec\.rb$})
25
+ end
26
+ end
@@ -1,37 +1,52 @@
1
- -- 0.1.0
2
- * Initial Public Release
3
1
 
4
- -- 0.1.1
5
- * Removed /lib/data_mapper/extensions
6
- * Moved ActiveRecordImpersonation into DataMapper::Support module
7
- * Moved CallbackHelper methods into DataMapper::Base class
8
- * Moved ValidationHelper into DataMapper::Validations module
9
- * Removed LoadedSet since it's not necessary for it to reference the Database, so it's nothing more than an array now; Replaced with Array
10
- * Modified data_mapper.rb to load DataMapper::Support::Enumerable
11
- * Modified example.rb and performance.rb to require 'lib/data_mapper' instead of modifying $LOADPATH
12
- * Created SqlAdapter base-class
13
- * Refactored MysqlAdapter to use SqlAdapter superclass
14
- * Refactored Sqlite3Adapter to use SqlAdapter superclass
15
- * Moved /lib/data_mapper/queries to /lib/data_mapper/adapters/sql/queries
16
- * Moved Connection, Result and Reader classes along with Coersion and Quoting modules to DataMapper::Adapters::Sql module
17
- * Moved DataMapper::Adapters::Sql::Queries to ::Commands
18
- * Moved Mappings to SqlAdapter
19
- * Added monolithic DeleteCommand
20
- * Added monolithic SaveCommand
21
- * Added TableExistsCommand
22
- * Moved save/delete logic out of Session
23
- * Added create-table functionality to SaveCommand
24
- * Cleaned up Session; #find no longer supported, use #all or #first
25
- * Moved object materialization into LoadCommand
26
- * Migrated Sqlite3Adapter::Commands
27
- * Added Session#query support back in
28
- * Removed Connection/Reader/Result classes
29
- * Set DataMapper::Base#key on load to avoid double-hit against Schema
30
- * Added DataMapper::Support::Struct for increased Session#query performance
31
- * Added AdvancedHasManyAssociation (preview status)
32
- * Added benchmarks comparing ActiveRecord::Base::find_by_sql with Session#query
2
+ == 0.3.0
3
+ * HasManyAssociation::Set now has a nil? method, so we can do stuff like cage.animal.nil?
4
+
5
+ == 0.2.5
6
+ * has_one bugfixes
7
+ * Added syntax for setting CHECK-constraints directly in your properties (Postgres)
8
+ * You can now set indexes with :index => true and :index => :unique
9
+ * Support for composite indexes (thanks to Jeffrey Gelens)
10
+ * Add composite scope to validates_uniqueness
11
+ * Added private/protected properties
12
+ * Remove HasOneAssociation, Make HasManyAssociation impersonate has_one relationships
13
+ * Added #get method
14
+ * Persistence module added, inheriting from DataMapper::Base no longer necessary
15
+
16
+ == 0.2.4
17
+ * Bug fixes
18
+ * Added paranoia
19
+
20
+ == 0.2.3
21
+ * Added String#t for translation and overrides for default validation messages
22
+ * Give credit where it's due: zapnap, not pimpmaster, submitted the String#blank? patch. My bad. :-(
23
+ * MAJOR: Resolve issue with non-unique-hash values and #dirty?; now frozen original values are stored instead
24
+ * Added Base#update_attributes
25
+ * MAJOR: Queries are now passed to the database drivers in a parameterized fashion
26
+ * Updated PostgreSQL driver and adapter to current
27
+
28
+ == 0.2.2
29
+ * Removed C extension bundles and log files from package
30
+
31
+ == 0.2.1
32
+ * Added :float column support
33
+ * Added association proxies: ie: Zoo.first.exhibits.animals
34
+ * Columns stored in SortedSet
35
+ * Swig files are no longer RDOCed
36
+ * Added :date column support
37
+ * BUG: Fixed UTC issues with datetimes
38
+ * Added #to_yaml method
39
+ * Added #to_xml method
40
+ * Added #to_json method
41
+ * BUG: Fixed HasManyAssociation::Set#inspect
42
+ * BUG: Fixed #reload!
43
+ * BUG: Column copy for STI moved into Table#initialize to better handle STI with multiple mapped databases
44
+ * BUG: before_create callbacks moved in the execution flow since they weren't guaranteed to fire before
45
+ * Threading enhancements: Removed single_threaded_mode, #database block form adjusted for thread-safety
46
+ * BUG: Fixed String#blank? when a multi-line string contained a blank line (thanks zapnap!)
47
+ * Performance enhancements: (thanks wycats!)
33
48
 
34
- -- 0.2.0
49
+ == 0.2.0
35
50
  * AdvancedHasManyAssociation now functional for fetches
36
51
  * AdvancedHasManyAssociation renamed to HasNAssociation
37
52
  * HasManyAssociation refactored to use HasNAssociation superclass
@@ -96,49 +111,35 @@
96
111
  * Most command implementations moved to methods in SqlAdapter
97
112
  * Removed UnitOfWork module, instead moving a slightly refactored implementation into Base
98
113
 
99
- -- 0.2.1
100
- * Added :float column support
101
- * Added association proxies: ie: Zoo.first.exhibits.animals
102
- * Columns stored in SortedSet
103
- * Swig files are no longer RDOCed
104
- * Added :date column support
105
- * BUG: Fixed UTC issues with datetimes
106
- * Added #to_yaml method
107
- * Added #to_xml method
108
- * Added #to_json method
109
- * BUG: Fixed HasManyAssociation::Set#inspect
110
- * BUG: Fixed #reload!
111
- * BUG: Column copy for STI moved into Table#initialize to better handle STI with multiple mapped databases
112
- * BUG: before_create callbacks moved in the execution flow since they weren't guaranteed to fire before
113
- * Threading enhancements: Removed single_threaded_mode, #database block form adjusted for thread-safety
114
- * BUG: Fixed String#blank? when a multi-line string contained a blank line (thanks zapnap!)
115
- * Performance enhancements: (thanks wycats!)
116
-
117
- -- 0.2.2
118
- * Removed C extension bundles and log files from package
119
-
120
- -- 0.2.3
121
- * Added String#t for translation and overrides for default validation messages
122
- * Give credit where it's due: zapnap, not pimpmaster, submitted the String#blank? patch. My bad. :-(
123
- * MAJOR: Resolve issue with non-unique-hash values and #dirty?; now frozen original values are stored instead
124
- * Added Base#update_attributes
125
- * MAJOR: Queries are now passed to the database drivers in a parameterized fashion
126
- * Updated PostgreSQL driver and adapter to current
127
-
128
- -- 0.2.4
129
- * Bug fixes
130
- * Added paranoia
131
-
132
- -- 0.2.5
133
- * has_one bugfixes
134
- * Added syntax for setting CHECK-constraints directly in your properties (Postgres)
135
- * You can now set indexes with :index => true and :index => :unique
136
- * Support for composite indexes (thanks to Jeffrey Gelens)
137
- * Add composite scope to validates_uniqueness
138
- * Added private/protected properties
139
- * Remove HasOneAssociation, Make HasManyAssociation impersonate has_one relationships
140
- * Added #get method
141
- * Persistence module added, inheriting from DataMapper::Base no longer necessary
114
+ == 0.1.1
115
+ * Removed /lib/data_mapper/extensions
116
+ * Moved ActiveRecordImpersonation into DataMapper::Support module
117
+ * Moved CallbackHelper methods into DataMapper::Base class
118
+ * Moved ValidationHelper into DataMapper::Validations module
119
+ * Removed LoadedSet since it's not necessary for it to reference the Database, so it's nothing more than an array now; Replaced with Array
120
+ * Modified data_mapper.rb to load DataMapper::Support::Enumerable
121
+ * Modified example.rb and performance.rb to require 'lib/data_mapper' instead of modifying $LOADPATH
122
+ * Created SqlAdapter base-class
123
+ * Refactored MysqlAdapter to use SqlAdapter superclass
124
+ * Refactored Sqlite3Adapter to use SqlAdapter superclass
125
+ * Moved /lib/data_mapper/queries to /lib/data_mapper/adapters/sql/queries
126
+ * Moved Connection, Result and Reader classes along with Coersion and Quoting modules to DataMapper::Adapters::Sql module
127
+ * Moved DataMapper::Adapters::Sql::Queries to ::Commands
128
+ * Moved Mappings to SqlAdapter
129
+ * Added monolithic DeleteCommand
130
+ * Added monolithic SaveCommand
131
+ * Added TableExistsCommand
132
+ * Moved save/delete logic out of Session
133
+ * Added create-table functionality to SaveCommand
134
+ * Cleaned up Session; #find no longer supported, use #all or #first
135
+ * Moved object materialization into LoadCommand
136
+ * Migrated Sqlite3Adapter::Commands
137
+ * Added Session#query support back in
138
+ * Removed Connection/Reader/Result classes
139
+ * Set DataMapper::Base#key on load to avoid double-hit against Schema
140
+ * Added DataMapper::Support::Struct for increased Session#query performance
141
+ * Added AdvancedHasManyAssociation (preview status)
142
+ * Added benchmarks comparing ActiveRecord::Base::find_by_sql with Session#query
142
143
 
143
- -- 0.3.0
144
- * HasManyAssociation::Set now has a nil? method, so we can do stuff like cage.animal.nil?
144
+ == 0.1.0
145
+ * Initial Public Release
data/Manifest.txt ADDED
@@ -0,0 +1,123 @@
1
+ .autotest
2
+ FAQ
3
+ History.txt
4
+ MIT-LICENSE
5
+ Manifest.txt
6
+ QUICKLINKS
7
+ README.txt
8
+ Rakefile
9
+ SPECS
10
+ TODO
11
+ lib/dm-core.rb
12
+ lib/dm-core/adapters.rb
13
+ lib/dm-core/adapters/abstract_adapter.rb
14
+ lib/dm-core/adapters/data_objects_adapter.rb
15
+ lib/dm-core/adapters/mysql_adapter.rb
16
+ lib/dm-core/adapters/postgres_adapter.rb
17
+ lib/dm-core/adapters/sqlite3_adapter.rb
18
+ lib/dm-core/associations.rb
19
+ lib/dm-core/associations/many_to_many.rb
20
+ lib/dm-core/associations/many_to_one.rb
21
+ lib/dm-core/associations/one_to_many.rb
22
+ lib/dm-core/associations/one_to_one.rb
23
+ lib/dm-core/associations/relationship.rb
24
+ lib/dm-core/associations/relationship_chain.rb
25
+ lib/dm-core/auto_migrations.rb
26
+ lib/dm-core/collection.rb
27
+ lib/dm-core/dependency_queue.rb
28
+ lib/dm-core/hook.rb
29
+ lib/dm-core/identity_map.rb
30
+ lib/dm-core/is.rb
31
+ lib/dm-core/logger.rb
32
+ lib/dm-core/migrations/destructive_migrations.rb
33
+ lib/dm-core/migrator.rb
34
+ lib/dm-core/model.rb
35
+ lib/dm-core/naming_conventions.rb
36
+ lib/dm-core/property.rb
37
+ lib/dm-core/property_set.rb
38
+ lib/dm-core/query.rb
39
+ lib/dm-core/repository.rb
40
+ lib/dm-core/resource.rb
41
+ lib/dm-core/scope.rb
42
+ lib/dm-core/support.rb
43
+ lib/dm-core/support/array.rb
44
+ lib/dm-core/support/assertions.rb
45
+ lib/dm-core/support/errors.rb
46
+ lib/dm-core/support/kernel.rb
47
+ lib/dm-core/support/symbol.rb
48
+ lib/dm-core/transaction.rb
49
+ lib/dm-core/type.rb
50
+ lib/dm-core/type_map.rb
51
+ lib/dm-core/types.rb
52
+ lib/dm-core/types/boolean.rb
53
+ lib/dm-core/types/discriminator.rb
54
+ lib/dm-core/types/object.rb
55
+ lib/dm-core/types/paranoid_boolean.rb
56
+ lib/dm-core/types/paranoid_datetime.rb
57
+ lib/dm-core/types/serial.rb
58
+ lib/dm-core/types/text.rb
59
+ lib/dm-core/version.rb
60
+ script/all
61
+ script/performance.rb
62
+ script/profile.rb
63
+ spec/integration/association_spec.rb
64
+ spec/integration/association_through_spec.rb
65
+ spec/integration/associations/many_to_many_spec.rb
66
+ spec/integration/associations/many_to_one_spec.rb
67
+ spec/integration/associations/one_to_many_spec.rb
68
+ spec/integration/auto_migrations_spec.rb
69
+ spec/integration/collection_spec.rb
70
+ spec/integration/data_objects_adapter_spec.rb
71
+ spec/integration/dependency_queue_spec.rb
72
+ spec/integration/model_spec.rb
73
+ spec/integration/mysql_adapter_spec.rb
74
+ spec/integration/postgres_adapter_spec.rb
75
+ spec/integration/property_spec.rb
76
+ spec/integration/query_spec.rb
77
+ spec/integration/repository_spec.rb
78
+ spec/integration/resource_spec.rb
79
+ spec/integration/sqlite3_adapter_spec.rb
80
+ spec/integration/sti_spec.rb
81
+ spec/integration/strategic_eager_loading_spec.rb
82
+ spec/integration/transaction_spec.rb
83
+ spec/integration/type_spec.rb
84
+ spec/lib/logging_helper.rb
85
+ spec/lib/mock_adapter.rb
86
+ spec/lib/model_loader.rb
87
+ spec/lib/publicize_methods.rb
88
+ spec/models/vehicles.rb
89
+ spec/models/zoo.rb
90
+ spec/spec.opts
91
+ spec/spec_helper.rb
92
+ spec/unit/adapters/abstract_adapter_spec.rb
93
+ spec/unit/adapters/adapter_shared_spec.rb
94
+ spec/unit/adapters/data_objects_adapter_spec.rb
95
+ spec/unit/adapters/postgres_adapter_spec.rb
96
+ spec/unit/associations/many_to_many_spec.rb
97
+ spec/unit/associations/many_to_one_spec.rb
98
+ spec/unit/associations/one_to_many_spec.rb
99
+ spec/unit/associations/one_to_one_spec.rb
100
+ spec/unit/associations/relationship_spec.rb
101
+ spec/unit/associations_spec.rb
102
+ spec/unit/auto_migrations_spec.rb
103
+ spec/unit/collection_spec.rb
104
+ spec/unit/data_mapper_spec.rb
105
+ spec/unit/identity_map_spec.rb
106
+ spec/unit/is_spec.rb
107
+ spec/unit/migrator_spec.rb
108
+ spec/unit/model_spec.rb
109
+ spec/unit/naming_conventions_spec.rb
110
+ spec/unit/property_set_spec.rb
111
+ spec/unit/property_spec.rb
112
+ spec/unit/query_spec.rb
113
+ spec/unit/repository_spec.rb
114
+ spec/unit/resource_spec.rb
115
+ spec/unit/scope_spec.rb
116
+ spec/unit/transaction_spec.rb
117
+ spec/unit/type_map_spec.rb
118
+ spec/unit/type_spec.rb
119
+ tasks/ci.rb
120
+ tasks/dm.rb
121
+ tasks/doc.rb
122
+ tasks/hoe.rb
123
+ tasks/install.rb
File without changes
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'rake/rdoctask'
6
+ require 'spec/rake/spectask'
7
+
8
+ require 'lib/dm-core/version'
9
+
10
+ ROOT = Pathname(__FILE__).dirname.expand_path
11
+
12
+ AUTHOR = "Sam Smoot"
13
+ EMAIL = "ssmoot@gmail.com"
14
+ GEM_NAME = "dm-core"
15
+ GEM_VERSION = DataMapper::VERSION
16
+ GEM_DEPENDENCIES = ["data_objects", GEM_VERSION], ["extlib", GEM_VERSION],
17
+ ["rspec", ">=1.1.3"], ["addressable", ">=1.0.4"]
18
+
19
+
20
+ PROJECT_NAME = "datamapper"
21
+ PROJECT_DESCRIPTION = "Faster, Better, Simpler."
22
+ PROJECT_SUMMARY = "An Object/Relational Mapper for Ruby"
23
+ PROJECT_URL = "http://datamapper.org"
24
+
25
+ require ROOT + 'tasks/hoe'
26
+ require ROOT + 'tasks/install'
27
+ require ROOT + 'tasks/dm'
28
+ require ROOT + 'tasks/doc'
29
+ require ROOT + 'tasks/ci'
data/SPECS ADDED
@@ -0,0 +1,63 @@
1
+ Reading Specs
2
+ =============
3
+
4
+ Blah blah blah...
5
+
6
+ Writing Specs
7
+ =============
8
+
9
+ Here are some general dos and don'ts
10
+
11
+ = DO:
12
+
13
+ * Write more specs for error conditions than clean conditions.
14
+ * Write specs with readability in mind. Somebody knew to DataMapper should be
15
+ able to read specs to learn how something works.
16
+ * Use existing models that are part of a metaphor.
17
+ * Nest describe blocks (2 or 3 levels deep is probably fine).
18
+ * Limit a describe block to 10 - 15 examples.
19
+ * Group specs by method being tested. (See the 'Ordering Specs' section)
20
+ * Use custom matchers.
21
+
22
+ = DON'T:
23
+
24
+ * Spec more than one unit of functionality in an example. An example should be
25
+ as short as possible (while still remaining readable).
26
+ * Spec implementation. Refactoring code should not break specs.
27
+ * Declare models in the spec file.
28
+
29
+ And a final do: Do go against the guidelines if your best judgement tells you
30
+ to. These are just guidelines and are obviously not fast rules.
31
+
32
+ Models
33
+ ======
34
+
35
+ Models are declared in separate files as opposed to individual spec files for
36
+ two reasons. The first is to improve readability. By creating as few models
37
+ as possible and sharing these models throughout the specs, a reader can
38
+ become familiar with the models being used quicker. Models also follow a
39
+ few simple metaphors, such as a zoo, a blog implementation, etc... Following
40
+ metaphors makes it easier for a reader to guess what is going on with respect
41
+ to the models.
42
+
43
+ The second reason is to allow the spec environment to be as pristine as
44
+ possible going into an example. Models being loaded from the model directory
45
+ are tracked and reloaded before each example. Any changes that might be made
46
+ to the model are reset at the end.
47
+
48
+ Mocks and Stubs
49
+ ===============
50
+
51
+ Obviously, mocks and stubs are a powerful feature when it comes to BDD;
52
+ however, remember that you are writing specs for behavior and NOT
53
+ implementation.
54
+
55
+ Ordering Specs
56
+ ==============
57
+
58
+ Specs aren't much use if nobody can find where anything is, so keeping specs
59
+ well organized is critical. Currently, we are trying out the following
60
+ structure:
61
+
62
+ * List guidelines here...
63
+
data/TODO ADDED
@@ -0,0 +1 @@
1
+ See: http://github.com/sam/dm-core/wikis
data/lib/dm-core.rb CHANGED
@@ -20,7 +20,7 @@ require 'rubygems'
20
20
  gem 'addressable', '>=1.0.4'
21
21
  require 'addressable/uri'
22
22
 
23
- gem 'extlib', '=0.9.2'
23
+ gem 'extlib', '=0.9.3'
24
24
  require 'extlib'
25
25
 
26
26
  begin
@@ -35,6 +35,7 @@ require dir / 'support'
35
35
  require dir / 'resource'
36
36
  require dir / 'model'
37
37
 
38
+ require dir / 'dependency_queue'
38
39
  require dir / 'type'
39
40
  require dir / 'type_map'
40
41
  require dir / 'types'
@@ -210,4 +211,8 @@ module DataMapper
210
211
  def self.prepare(*args, &blk)
211
212
  yield repository(*args)
212
213
  end
214
+
215
+ def self.dependency_queue
216
+ @dependency_queue ||= DependencyQueue.new
217
+ end
213
218
  end
@@ -1,4 +1,4 @@
1
- gem 'data_objects', '=0.9.2'
1
+ gem 'data_objects', '=0.9.3'
2
2
  require 'data_objects'
3
3
 
4
4
  module DataMapper
@@ -228,6 +228,7 @@ module DataMapper
228
228
  statement << " FROM #{quote_table_name(query.model.storage_name(query.repository.name))}"
229
229
  statement << links_statement(query) if query.links.any?
230
230
  statement << " WHERE #{conditions_statement(query)}" if query.conditions.any?
231
+ statement << " GROUP BY #{group_by_statement(query)}" if query.unique? && query.fields.any? { |p| p.kind_of?(Property) }
231
232
  statement << " ORDER BY #{order_statement(query)}" if query.order.any?
232
233
  statement << " LIMIT #{quote_column_value(query.limit)}" if query.limit
233
234
  statement << " OFFSET #{quote_column_value(query.offset)}" if query.offset && query.offset > 0
@@ -256,17 +257,7 @@ module DataMapper
256
257
 
257
258
  def fields_statement(query)
258
259
  qualify = query.links.any?
259
-
260
- query.fields.map do |property|
261
- # TODO Should we raise an error if there is no such property in the
262
- # repository of the query?
263
- #
264
- #if property.model.properties(query.repository.name)[property.name].nil?
265
- # raise "Property #{property.model.to_s}.#{property.name.to_s} not available in repository #{name}."
266
- #end
267
- #
268
- property_to_column_name(query.repository, property, qualify)
269
- end * ', '
260
+ query.fields.map { |p| property_to_column_name(query.repository, p, qualify) } * ', '
270
261
  end
271
262
 
272
263
  def links_statement(query)
@@ -292,29 +283,35 @@ module DataMapper
292
283
  end
293
284
 
294
285
  def conditions_statement(query)
295
- query.conditions.map do |operator, property, bind_value|
296
- condition_statement(query, operator, property, bind_value)
297
- end * ' AND '
286
+ query.conditions.map { |o,p,b| condition_statement(query, o, p, b) } * ' AND '
287
+ end
288
+
289
+ def group_by_statement(query)
290
+ repository = query.repository
291
+ qualify = query.links.any?
292
+ query.fields.select { |p| p.kind_of?(Property) }.map { |p| property_to_column_name(repository, p, qualify) } * ', '
298
293
  end
299
294
 
300
295
  def order_statement(query)
301
- qualify = query.links.any?
296
+ repository = query.repository
297
+ qualify = query.links.any?
298
+ query.order.map { |i| order_column(repository, i, qualify) } * ', '
299
+ end
302
300
 
303
- query.order.map do |item|
304
- property, descending = nil, false
301
+ def order_column(repository, item, qualify)
302
+ property, descending = nil, false
305
303
 
306
- case item
307
- when Property
308
- property = item
309
- when Query::Direction
310
- property = item.property
311
- descending = true if item.direction == :desc
312
- end
304
+ case item
305
+ when Property
306
+ property = item
307
+ when Query::Direction
308
+ property = item.property
309
+ descending = true if item.direction == :desc
310
+ end
313
311
 
314
- order = property_to_column_name(query.repository, property, qualify)
315
- order << ' DESC' if descending
316
- order
317
- end * ', '
312
+ order_column = property_to_column_name(repository, property, qualify)
313
+ order_column << ' DESC' if descending
314
+ order_column
318
315
  end
319
316
 
320
317
  def condition_statement(query, operator, left_condition, right_condition)
@@ -330,7 +327,7 @@ module DataMapper
330
327
  query.merge_subquery(operator, opposite, condition)
331
328
  "(#{read_statement(condition)})"
332
329
  elsif condition.kind_of?(Array) && condition.all? { |p| p.kind_of?(Property) }
333
- "(#{condition.map { |p| property_to_column_name(query.repository, property, qualify) } * ', '})"
330
+ "(#{condition.map { |p| property_to_column_name(query.repository, p, qualify) } * ', '})"
334
331
  else
335
332
  '?'
336
333
  end
@@ -598,8 +595,8 @@ module DataMapper
598
595
  tm.map(String).to('VARCHAR').with(:size => Property::DEFAULT_LENGTH)
599
596
  tm.map(Class).to('VARCHAR').with(:size => Property::DEFAULT_LENGTH)
600
597
  tm.map(DM::Discriminator).to('VARCHAR').with(:size => Property::DEFAULT_LENGTH)
601
- tm.map(BigDecimal).to('DECIMAL').with(:precision => Property::DEFAULT_PRECISION, :scale => Property::DEFAULT_SCALE)
602
- tm.map(Float).to('FLOAT').with(:precision => Property::DEFAULT_PRECISION, :scale => Property::DEFAULT_SCALE)
598
+ tm.map(BigDecimal).to('DECIMAL').with(:precision => Property::DEFAULT_PRECISION, :scale => Property::DEFAULT_SCALE_BIGDECIMAL)
599
+ tm.map(Float).to('FLOAT').with(:precision => Property::DEFAULT_PRECISION)
603
600
  tm.map(DateTime).to('DATETIME')
604
601
  tm.map(Date).to('DATE')
605
602
  tm.map(Time).to('TIMESTAMP')