rpbertp13-dm-core 0.9.11.1

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/.autotest +26 -0
  2. data/.gitignore +18 -0
  3. data/CONTRIBUTING +51 -0
  4. data/FAQ +92 -0
  5. data/History.txt +52 -0
  6. data/MIT-LICENSE +22 -0
  7. data/Manifest.txt +130 -0
  8. data/QUICKLINKS +11 -0
  9. data/README.txt +143 -0
  10. data/Rakefile +32 -0
  11. data/SPECS +62 -0
  12. data/TODO +1 -0
  13. data/dm-core.gemspec +40 -0
  14. data/lib/dm-core.rb +217 -0
  15. data/lib/dm-core/adapters.rb +16 -0
  16. data/lib/dm-core/adapters/abstract_adapter.rb +209 -0
  17. data/lib/dm-core/adapters/data_objects_adapter.rb +716 -0
  18. data/lib/dm-core/adapters/in_memory_adapter.rb +87 -0
  19. data/lib/dm-core/adapters/mysql_adapter.rb +138 -0
  20. data/lib/dm-core/adapters/postgres_adapter.rb +189 -0
  21. data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
  22. data/lib/dm-core/associations.rb +207 -0
  23. data/lib/dm-core/associations/many_to_many.rb +147 -0
  24. data/lib/dm-core/associations/many_to_one.rb +107 -0
  25. data/lib/dm-core/associations/one_to_many.rb +315 -0
  26. data/lib/dm-core/associations/one_to_one.rb +61 -0
  27. data/lib/dm-core/associations/relationship.rb +221 -0
  28. data/lib/dm-core/associations/relationship_chain.rb +81 -0
  29. data/lib/dm-core/auto_migrations.rb +105 -0
  30. data/lib/dm-core/collection.rb +670 -0
  31. data/lib/dm-core/dependency_queue.rb +32 -0
  32. data/lib/dm-core/hook.rb +11 -0
  33. data/lib/dm-core/identity_map.rb +42 -0
  34. data/lib/dm-core/is.rb +16 -0
  35. data/lib/dm-core/logger.rb +232 -0
  36. data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
  37. data/lib/dm-core/migrator.rb +29 -0
  38. data/lib/dm-core/model.rb +526 -0
  39. data/lib/dm-core/naming_conventions.rb +84 -0
  40. data/lib/dm-core/property.rb +676 -0
  41. data/lib/dm-core/property_set.rb +169 -0
  42. data/lib/dm-core/query.rb +676 -0
  43. data/lib/dm-core/repository.rb +167 -0
  44. data/lib/dm-core/resource.rb +671 -0
  45. data/lib/dm-core/scope.rb +58 -0
  46. data/lib/dm-core/support.rb +7 -0
  47. data/lib/dm-core/support/array.rb +13 -0
  48. data/lib/dm-core/support/assertions.rb +8 -0
  49. data/lib/dm-core/support/errors.rb +23 -0
  50. data/lib/dm-core/support/kernel.rb +11 -0
  51. data/lib/dm-core/support/symbol.rb +41 -0
  52. data/lib/dm-core/transaction.rb +252 -0
  53. data/lib/dm-core/type.rb +160 -0
  54. data/lib/dm-core/type_map.rb +80 -0
  55. data/lib/dm-core/types.rb +19 -0
  56. data/lib/dm-core/types/boolean.rb +7 -0
  57. data/lib/dm-core/types/discriminator.rb +34 -0
  58. data/lib/dm-core/types/object.rb +24 -0
  59. data/lib/dm-core/types/paranoid_boolean.rb +34 -0
  60. data/lib/dm-core/types/paranoid_datetime.rb +33 -0
  61. data/lib/dm-core/types/serial.rb +9 -0
  62. data/lib/dm-core/types/text.rb +10 -0
  63. data/lib/dm-core/version.rb +3 -0
  64. data/script/all +4 -0
  65. data/script/performance.rb +282 -0
  66. data/script/profile.rb +87 -0
  67. data/spec/integration/association_spec.rb +1382 -0
  68. data/spec/integration/association_through_spec.rb +203 -0
  69. data/spec/integration/associations/many_to_many_spec.rb +449 -0
  70. data/spec/integration/associations/many_to_one_spec.rb +163 -0
  71. data/spec/integration/associations/one_to_many_spec.rb +188 -0
  72. data/spec/integration/auto_migrations_spec.rb +413 -0
  73. data/spec/integration/collection_spec.rb +1073 -0
  74. data/spec/integration/data_objects_adapter_spec.rb +32 -0
  75. data/spec/integration/dependency_queue_spec.rb +46 -0
  76. data/spec/integration/model_spec.rb +197 -0
  77. data/spec/integration/mysql_adapter_spec.rb +85 -0
  78. data/spec/integration/postgres_adapter_spec.rb +731 -0
  79. data/spec/integration/property_spec.rb +253 -0
  80. data/spec/integration/query_spec.rb +514 -0
  81. data/spec/integration/repository_spec.rb +61 -0
  82. data/spec/integration/resource_spec.rb +513 -0
  83. data/spec/integration/sqlite3_adapter_spec.rb +352 -0
  84. data/spec/integration/sti_spec.rb +273 -0
  85. data/spec/integration/strategic_eager_loading_spec.rb +156 -0
  86. data/spec/integration/transaction_spec.rb +60 -0
  87. data/spec/integration/type_spec.rb +275 -0
  88. data/spec/lib/logging_helper.rb +18 -0
  89. data/spec/lib/mock_adapter.rb +27 -0
  90. data/spec/lib/model_loader.rb +100 -0
  91. data/spec/lib/publicize_methods.rb +28 -0
  92. data/spec/models/content.rb +16 -0
  93. data/spec/models/vehicles.rb +34 -0
  94. data/spec/models/zoo.rb +48 -0
  95. data/spec/spec.opts +3 -0
  96. data/spec/spec_helper.rb +91 -0
  97. data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
  98. data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
  99. data/spec/unit/adapters/data_objects_adapter_spec.rb +632 -0
  100. data/spec/unit/adapters/in_memory_adapter_spec.rb +98 -0
  101. data/spec/unit/adapters/postgres_adapter_spec.rb +133 -0
  102. data/spec/unit/associations/many_to_many_spec.rb +32 -0
  103. data/spec/unit/associations/many_to_one_spec.rb +159 -0
  104. data/spec/unit/associations/one_to_many_spec.rb +393 -0
  105. data/spec/unit/associations/one_to_one_spec.rb +7 -0
  106. data/spec/unit/associations/relationship_spec.rb +71 -0
  107. data/spec/unit/associations_spec.rb +242 -0
  108. data/spec/unit/auto_migrations_spec.rb +111 -0
  109. data/spec/unit/collection_spec.rb +182 -0
  110. data/spec/unit/data_mapper_spec.rb +35 -0
  111. data/spec/unit/identity_map_spec.rb +126 -0
  112. data/spec/unit/is_spec.rb +80 -0
  113. data/spec/unit/migrator_spec.rb +33 -0
  114. data/spec/unit/model_spec.rb +321 -0
  115. data/spec/unit/naming_conventions_spec.rb +36 -0
  116. data/spec/unit/property_set_spec.rb +90 -0
  117. data/spec/unit/property_spec.rb +753 -0
  118. data/spec/unit/query_spec.rb +571 -0
  119. data/spec/unit/repository_spec.rb +93 -0
  120. data/spec/unit/resource_spec.rb +649 -0
  121. data/spec/unit/scope_spec.rb +142 -0
  122. data/spec/unit/transaction_spec.rb +469 -0
  123. data/spec/unit/type_map_spec.rb +114 -0
  124. data/spec/unit/type_spec.rb +119 -0
  125. data/tasks/ci.rb +36 -0
  126. data/tasks/dm.rb +63 -0
  127. data/tasks/doc.rb +20 -0
  128. data/tasks/gemspec.rb +23 -0
  129. data/tasks/hoe.rb +46 -0
  130. data/tasks/install.rb +20 -0
  131. metadata +215 -0
data/Rakefile ADDED
@@ -0,0 +1,32 @@
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 = 'Dan Kubb'
13
+ EMAIL = 'dan.kubb@gmail.com'
14
+ GEM_NAME = 'dm-core'
15
+ GEM_VERSION = DataMapper::VERSION
16
+ GEM_DEPENDENCIES = [
17
+ %w[ data_objects ~>0.9.11 ],
18
+ %w[ extlib ~>0.9.11 ],
19
+ %w[ addressable ~>2.0.2 ],
20
+ ]
21
+
22
+ PROJECT_NAME = 'datamapper'
23
+ PROJECT_DESCRIPTION = 'Faster, Better, Simpler.'
24
+ PROJECT_SUMMARY = 'An Object/Relational Mapper for Ruby'
25
+ PROJECT_URL = 'http://datamapper.org'
26
+
27
+ require ROOT + 'tasks/hoe'
28
+ require ROOT + 'tasks/gemspec'
29
+ require ROOT + 'tasks/install'
30
+ require ROOT + 'tasks/dm'
31
+ require ROOT + 'tasks/doc'
32
+ require ROOT + 'tasks/ci'
data/SPECS ADDED
@@ -0,0 +1,62 @@
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...
data/TODO ADDED
@@ -0,0 +1 @@
1
+ See: http://github.com/sam/dm-core/wikis
data/dm-core.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{dm-core}
5
+ s.version = "0.9.11.1"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Dan Kubb"]
9
+ s.date = %q{2009-03-29}
10
+ s.description = %q{Faster, Better, Simpler.}
11
+ s.email = ["dan.kubb@gmail.com"]
12
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt", "README.txt"]
13
+ s.files = [".autotest", ".gitignore", "CONTRIBUTING", "FAQ", "History.txt", "MIT-LICENSE", "Manifest.txt", "QUICKLINKS", "README.txt", "Rakefile", "SPECS", "TODO", "dm-core.gemspec", "lib/dm-core.rb", "lib/dm-core/adapters.rb", "lib/dm-core/adapters/abstract_adapter.rb", "lib/dm-core/adapters/data_objects_adapter.rb", "lib/dm-core/adapters/in_memory_adapter.rb", "lib/dm-core/adapters/mysql_adapter.rb", "lib/dm-core/adapters/postgres_adapter.rb", "lib/dm-core/adapters/sqlite3_adapter.rb", "lib/dm-core/associations.rb", "lib/dm-core/associations/many_to_many.rb", "lib/dm-core/associations/many_to_one.rb", "lib/dm-core/associations/one_to_many.rb", "lib/dm-core/associations/one_to_one.rb", "lib/dm-core/associations/relationship.rb", "lib/dm-core/associations/relationship_chain.rb", "lib/dm-core/auto_migrations.rb", "lib/dm-core/collection.rb", "lib/dm-core/dependency_queue.rb", "lib/dm-core/hook.rb", "lib/dm-core/identity_map.rb", "lib/dm-core/is.rb", "lib/dm-core/logger.rb", "lib/dm-core/migrations/destructive_migrations.rb", "lib/dm-core/migrator.rb", "lib/dm-core/model.rb", "lib/dm-core/naming_conventions.rb", "lib/dm-core/property.rb", "lib/dm-core/property_set.rb", "lib/dm-core/query.rb", "lib/dm-core/repository.rb", "lib/dm-core/resource.rb", "lib/dm-core/scope.rb", "lib/dm-core/support.rb", "lib/dm-core/support/array.rb", "lib/dm-core/support/assertions.rb", "lib/dm-core/support/errors.rb", "lib/dm-core/support/kernel.rb", "lib/dm-core/support/symbol.rb", "lib/dm-core/transaction.rb", "lib/dm-core/type.rb", "lib/dm-core/type_map.rb", "lib/dm-core/types.rb", "lib/dm-core/types/boolean.rb", "lib/dm-core/types/discriminator.rb", "lib/dm-core/types/object.rb", "lib/dm-core/types/paranoid_boolean.rb", "lib/dm-core/types/paranoid_datetime.rb", "lib/dm-core/types/serial.rb", "lib/dm-core/types/text.rb", "lib/dm-core/version.rb", "script/all", "script/performance.rb", "script/profile.rb", "spec/integration/association_spec.rb", "spec/integration/association_through_spec.rb", "spec/integration/associations/many_to_many_spec.rb", "spec/integration/associations/many_to_one_spec.rb", "spec/integration/associations/one_to_many_spec.rb", "spec/integration/auto_migrations_spec.rb", "spec/integration/collection_spec.rb", "spec/integration/data_objects_adapter_spec.rb", "spec/integration/dependency_queue_spec.rb", "spec/integration/model_spec.rb", "spec/integration/mysql_adapter_spec.rb", "spec/integration/postgres_adapter_spec.rb", "spec/integration/property_spec.rb", "spec/integration/query_spec.rb", "spec/integration/repository_spec.rb", "spec/integration/resource_spec.rb", "spec/integration/sqlite3_adapter_spec.rb", "spec/integration/sti_spec.rb", "spec/integration/strategic_eager_loading_spec.rb", "spec/integration/transaction_spec.rb", "spec/integration/type_spec.rb", "spec/lib/logging_helper.rb", "spec/lib/mock_adapter.rb", "spec/lib/model_loader.rb", "spec/lib/publicize_methods.rb", "spec/models/content.rb", "spec/models/vehicles.rb", "spec/models/zoo.rb", "spec/spec.opts", "spec/spec_helper.rb", "spec/unit/adapters/abstract_adapter_spec.rb", "spec/unit/adapters/adapter_shared_spec.rb", "spec/unit/adapters/data_objects_adapter_spec.rb", "spec/unit/adapters/in_memory_adapter_spec.rb", "spec/unit/adapters/postgres_adapter_spec.rb", "spec/unit/associations/many_to_many_spec.rb", "spec/unit/associations/many_to_one_spec.rb", "spec/unit/associations/one_to_many_spec.rb", "spec/unit/associations/one_to_one_spec.rb", "spec/unit/associations/relationship_spec.rb", "spec/unit/associations_spec.rb", "spec/unit/auto_migrations_spec.rb", "spec/unit/collection_spec.rb", "spec/unit/data_mapper_spec.rb", "spec/unit/identity_map_spec.rb", "spec/unit/is_spec.rb", "spec/unit/migrator_spec.rb", "spec/unit/model_spec.rb", "spec/unit/naming_conventions_spec.rb", "spec/unit/property_set_spec.rb", "spec/unit/property_spec.rb", "spec/unit/query_spec.rb", "spec/unit/repository_spec.rb", "spec/unit/resource_spec.rb", "spec/unit/scope_spec.rb", "spec/unit/transaction_spec.rb", "spec/unit/type_map_spec.rb", "spec/unit/type_spec.rb", "tasks/ci.rb", "tasks/dm.rb", "tasks/doc.rb", "tasks/gemspec.rb", "tasks/hoe.rb", "tasks/install.rb"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://datamapper.org}
16
+ s.rdoc_options = ["--main", "README.txt"]
17
+ s.require_paths = ["lib"]
18
+ s.rubyforge_project = %q{datamapper}
19
+ s.rubygems_version = %q{1.3.1}
20
+ s.summary = %q{An Object/Relational Mapper for Ruby}
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 2
25
+
26
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<data_objects>, ["~> 0.10.0"])
28
+ s.add_runtime_dependency(%q<extlib>, ["~> 0.9.11"])
29
+ s.add_runtime_dependency(%q<addressable>, ["~> 2.0"])
30
+ else
31
+ s.add_dependency(%q<data_objects>, ["~> 0.10.0"])
32
+ s.add_dependency(%q<extlib>, ["~> 0.9.11"])
33
+ s.add_dependency(%q<addressable>, ["~> 2.0"])
34
+ end
35
+ else
36
+ s.add_dependency(%q<data_objects>, ["~> 0.10.0"])
37
+ s.add_dependency(%q<extlib>, ["~> 0.9.11"])
38
+ s.add_dependency(%q<addressable>, ["~> 2.0"])
39
+ end
40
+ end
data/lib/dm-core.rb ADDED
@@ -0,0 +1,217 @@
1
+ # This file begins the loading sequence.
2
+ #
3
+ # Quick Overview:
4
+ # * Requires fastthread, support libs, and base.
5
+ # * Sets the application root and environment for compatibility with frameworks
6
+ # such as Rails or Merb.
7
+ # * Checks for the database.yml and loads it if it exists.
8
+ # * Sets up the database using the config from the Yaml file or from the
9
+ # environment.
10
+ #
11
+
12
+ require 'date'
13
+ require 'pathname'
14
+ require 'rubygems'
15
+ require 'set'
16
+ require 'time'
17
+ require 'yaml'
18
+
19
+ gem 'addressable', '~>2.0'
20
+ require 'addressable/uri'
21
+
22
+ gem 'extlib', '~>0.9.11'
23
+ require 'extlib'
24
+ require 'extlib/inflection'
25
+
26
+ begin
27
+ gem 'fastthread', '~>1.0.4'
28
+ require 'fastthread'
29
+ rescue LoadError
30
+ # fastthread not installed
31
+ end
32
+
33
+ dir = Pathname(__FILE__).dirname.expand_path / 'dm-core'
34
+
35
+ require dir / 'support'
36
+ require dir / 'resource'
37
+ require dir / 'model'
38
+
39
+ require dir / 'dependency_queue'
40
+ require dir / 'type'
41
+ require dir / 'type_map'
42
+ require dir / 'types'
43
+ require dir / 'hook'
44
+ require dir / 'associations'
45
+ require dir / 'auto_migrations'
46
+ require dir / 'identity_map'
47
+ require dir / 'logger'
48
+ require dir / 'migrator'
49
+ require dir / 'naming_conventions'
50
+ require dir / 'property_set'
51
+ require dir / 'query'
52
+ require dir / 'transaction'
53
+ require dir / 'repository'
54
+ require dir / 'scope'
55
+ require dir / 'property'
56
+ require dir / 'adapters'
57
+ require dir / 'collection'
58
+ require dir / 'is'
59
+
60
+ # == Setup and Configuration
61
+ # DataMapper uses URIs or a connection hash to connect to your data-store.
62
+ # URI connections takes the form of:
63
+ # DataMapper.setup(:default, 'protocol://username:password@localhost:port/path/to/repo')
64
+ #
65
+ # Breaking this down, the first argument is the name you wish to give this
66
+ # connection. If you do not specify one, it will be assigned :default. If you
67
+ # would like to connect to more than one data-store, simply issue this command
68
+ # again, but with a different name specified.
69
+ #
70
+ # In order to issue ORM commands without specifying the repository context, you
71
+ # must define the :default database. Otherwise, you'll need to wrap your ORM
72
+ # calls in <tt>repository(:name) { }</tt>.
73
+ #
74
+ # Second, the URI breaks down into the access protocol, the username, the
75
+ # server, the password, and whatever path information is needed to properly
76
+ # address the data-store on the server.
77
+ #
78
+ # Here's some examples
79
+ # DataMapper.setup(:default, "sqlite3://path/to/your/project/db/development.db")
80
+ # DataMapper.setup(:default, "mysql://localhost/dm_core_test")
81
+ # # no auth-info
82
+ # DataMapper.setup(:default, "postgres://root:supahsekret@127.0.0.1/dm_core_test")
83
+ # # with auth-info
84
+ #
85
+ #
86
+ # Alternatively, you can supply a hash as the second parameter, which would
87
+ # take the form:
88
+ #
89
+ # DataMapper.setup(:default, {
90
+ # :adapter => 'adapter_name_here',
91
+ # :database => "path/to/repo",
92
+ # :username => 'username',
93
+ # :password => 'password',
94
+ # :host => 'hostname'
95
+ # })
96
+ #
97
+ # === Logging
98
+ # To turn on error logging to STDOUT, issue:
99
+ #
100
+ # DataMapper::Logger.new(STDOUT, 0)
101
+ #
102
+ # You can pass a file location ("/path/to/log/file.log") in place of STDOUT.
103
+ # see DataMapper::Logger for more information.
104
+ #
105
+ module DataMapper
106
+ extend Assertions
107
+
108
+ def self.root
109
+ @root ||= Pathname(__FILE__).dirname.parent.expand_path
110
+ end
111
+
112
+ ##
113
+ # Setups up a connection to a data-store
114
+ #
115
+ # @param Symbol name a name for the context, defaults to :default
116
+ # @param [Hash{Symbol => String}, Addressable::URI, String] uri_or_options
117
+ # connection information
118
+ #
119
+ # @return Repository the resulting setup repository
120
+ #
121
+ # @raise ArgumentError "+name+ must be a Symbol, but was..." indicates that
122
+ # an invalid argument was passed for name[Symbol]
123
+ # @raise [ArgumentError] "+uri_or_options+ must be a Hash, URI or String,
124
+ # but was..." indicates that connection information could not be gleaned
125
+ # from the given uri_or_options<Hash, Addressable::URI, String>
126
+ #
127
+ # -
128
+ # @api public
129
+ def self.setup(name, uri_or_options)
130
+ assert_kind_of 'name', name, Symbol
131
+ assert_kind_of 'uri_or_options', uri_or_options, Addressable::URI, Hash, String
132
+
133
+ case uri_or_options
134
+ when Hash
135
+ adapter_name = uri_or_options[:adapter].to_s
136
+ when String, DataObjects::URI, Addressable::URI
137
+ uri_or_options = DataObjects::URI.parse(uri_or_options) if uri_or_options.kind_of?(String)
138
+ adapter_name = uri_or_options.scheme
139
+ end
140
+
141
+ class_name = Extlib::Inflection.classify(adapter_name) + 'Adapter'
142
+
143
+ unless Adapters::const_defined?(class_name)
144
+ lib_name = "#{Extlib::Inflection.underscore(adapter_name)}_adapter"
145
+ begin
146
+ require root / 'lib' / 'dm-core' / 'adapters' / lib_name
147
+ rescue LoadError => e
148
+ begin
149
+ require lib_name
150
+ rescue Exception
151
+ # library not found, raise the original error
152
+ raise e
153
+ end
154
+ end
155
+ end
156
+
157
+ Repository.adapters[name] = Adapters::const_get(class_name).new(name, uri_or_options)
158
+ end
159
+
160
+ ##
161
+ # Block Syntax
162
+ # Pushes the named repository onto the context-stack,
163
+ # yields a new session, and pops the context-stack.
164
+ #
165
+ # Non-Block Syntax
166
+ # Returns the current session, or if there is none,
167
+ # a new Session.
168
+ #
169
+ # @param [Symbol] args the name of a repository to act within or return, :default is default
170
+ # @yield [Proc] (optional) block to execute within the context of the named repository
171
+ # @demo spec/integration/repository_spec.rb
172
+ def self.repository(name = nil) # :yields: current_context
173
+ current_repository = if name
174
+ raise ArgumentError, "First optional argument must be a Symbol, but was #{name.inspect}" unless name.is_a?(Symbol)
175
+ Repository.context.detect { |r| r.name == name } || Repository.new(name)
176
+ else
177
+ Repository.context.last || Repository.new(Repository.default_name)
178
+ end
179
+
180
+ if block_given?
181
+ current_repository.scope { |*block_args| yield(*block_args) }
182
+ else
183
+ current_repository
184
+ end
185
+ end
186
+
187
+ # A logger should always be present. Lets be consistent with DO
188
+ Logger.new(nil, :off)
189
+
190
+ ##
191
+ # destructively migrates the repository upwards to match model definitions
192
+ #
193
+ # @param [Symbol] name repository to act on, :default is the default
194
+ def self.migrate!(name = Repository.default_name)
195
+ repository(name).migrate!
196
+ end
197
+
198
+ ##
199
+ # drops and recreates the repository upwards to match model definitions
200
+ #
201
+ # @param [Symbol] name repository to act on, :default is the default
202
+ def self.auto_migrate!(repository_name = nil)
203
+ AutoMigrator.auto_migrate(repository_name)
204
+ end
205
+
206
+ def self.auto_upgrade!(repository_name = nil)
207
+ AutoMigrator.auto_upgrade(repository_name)
208
+ end
209
+
210
+ def self.prepare(*args, &blk)
211
+ yield repository(*args)
212
+ end
213
+
214
+ def self.dependency_queue
215
+ @dependency_queue ||= DependencyQueue.new
216
+ end
217
+ end
@@ -0,0 +1,16 @@
1
+ dir = Pathname(__FILE__).dirname.expand_path / 'adapters'
2
+
3
+ require dir / 'abstract_adapter'
4
+ require dir / 'in_memory_adapter'
5
+
6
+ # NOTE: this is a temporary work-around to the load error problems,
7
+ # and is better fixed in dm-core/next. The main reason the fix is
8
+ # not applied in dm-core/master is because the change is non-trivial.
9
+
10
+ %w[ data_objects sqlite3 mysql postgres ].each do |gem|
11
+ begin
12
+ require dir / "#{gem}_adapter"
13
+ rescue LoadError, Gem::Exception
14
+ # ignore it
15
+ end
16
+ end
@@ -0,0 +1,209 @@
1
+ module DataMapper
2
+ module Adapters
3
+ class AbstractAdapter
4
+ include Assertions
5
+
6
+ attr_reader :name, :uri
7
+ attr_accessor :resource_naming_convention, :field_naming_convention
8
+
9
+ def create(resources)
10
+ raise NotImplementedError
11
+ end
12
+
13
+ def read_many(query)
14
+ raise NotImplementedError
15
+ end
16
+
17
+ def read_one(query)
18
+ raise NotImplementedError
19
+ end
20
+
21
+ def update(attributes, query)
22
+ raise NotImplementedError
23
+ end
24
+
25
+ def delete(query)
26
+ raise NotImplementedError
27
+ end
28
+
29
+ protected
30
+
31
+ def normalize_uri(uri_or_options)
32
+ uri_or_options
33
+ end
34
+
35
+ private
36
+
37
+ # Instantiate an Adapter by passing it a DataMapper::Repository
38
+ # connection string for configuration.
39
+ def initialize(name, uri_or_options)
40
+ assert_kind_of 'name', name, Symbol
41
+ assert_kind_of 'uri_or_options', uri_or_options, Addressable::URI, DataObjects::URI, Hash, String
42
+
43
+ @name = name
44
+ @uri = normalize_uri(uri_or_options)
45
+
46
+ @resource_naming_convention = NamingConventions::Resource::UnderscoredAndPluralized
47
+ @field_naming_convention = NamingConventions::Field::Underscored
48
+
49
+ @transactions = {}
50
+ end
51
+
52
+ # TODO: move to dm-more/dm-migrations
53
+ module Migration
54
+ #
55
+ # Returns whether the storage_name exists.
56
+ #
57
+ # @param storage_name<String> a String defining the name of a storage,
58
+ # for example a table name.
59
+ #
60
+ # @return <Boolean> true if the storage exists
61
+ #
62
+ # TODO: move to dm-more/dm-migrations (if possible)
63
+ def storage_exists?(storage_name)
64
+ raise NotImplementedError
65
+ end
66
+
67
+ #
68
+ # Returns whether the field exists.
69
+ #
70
+ # @param storage_name<String> a String defining the name of a storage, for example a table name.
71
+ # @param field_name<String> a String defining the name of a field, for example a column name.
72
+ #
73
+ # @return <Boolean> true if the field exists.
74
+ #
75
+ # TODO: move to dm-more/dm-migrations (if possible)
76
+ def field_exists?(storage_name, field_name)
77
+ raise NotImplementedError
78
+ end
79
+
80
+ # TODO: move to dm-more/dm-migrations
81
+ def upgrade_model_storage(repository, model)
82
+ raise NotImplementedError
83
+ end
84
+
85
+ # TODO: move to dm-more/dm-migrations
86
+ def create_model_storage(repository, model)
87
+ raise NotImplementedError
88
+ end
89
+
90
+ # TODO: move to dm-more/dm-migrations
91
+ def destroy_model_storage(repository, model)
92
+ raise NotImplementedError
93
+ end
94
+
95
+ # TODO: move to dm-more/dm-migrations
96
+ def alter_model_storage(repository, *args)
97
+ raise NotImplementedError
98
+ end
99
+
100
+ # TODO: move to dm-more/dm-migrations
101
+ def create_property_storage(repository, property)
102
+ raise NotImplementedError
103
+ end
104
+
105
+ # TODO: move to dm-more/dm-migrations
106
+ def destroy_property_storage(repository, property)
107
+ raise NotImplementedError
108
+ end
109
+
110
+ # TODO: move to dm-more/dm-migrations
111
+ def alter_property_storage(repository, *args)
112
+ raise NotImplementedError
113
+ end
114
+
115
+ module ClassMethods
116
+ # Default TypeMap for all adapters.
117
+ #
118
+ # @return <DataMapper::TypeMap> default TypeMap
119
+ #
120
+ # TODO: move to dm-more/dm-migrations
121
+ def type_map
122
+ @type_map ||= TypeMap.new
123
+ end
124
+ end
125
+ end
126
+
127
+ include Migration
128
+ extend Migration::ClassMethods
129
+
130
+ # TODO: move to dm-more/dm-transaction
131
+ module Transaction
132
+ #
133
+ # Pushes the given Transaction onto the per thread Transaction stack so
134
+ # that everything done by this Adapter is done within the context of said
135
+ # Transaction.
136
+ #
137
+ # @param transaction<DataMapper::Transaction> a Transaction to be the
138
+ # 'current' transaction until popped.
139
+ #
140
+ # TODO: move to dm-more/dm-transaction
141
+ def push_transaction(transaction)
142
+ transactions(Thread.current) << transaction
143
+ end
144
+
145
+ #
146
+ # Pop the 'current' Transaction from the per thread Transaction stack so
147
+ # that everything done by this Adapter is no longer necessarily within the
148
+ # context of said Transaction.
149
+ #
150
+ # @return <DataMapper::Transaction> the former 'current' transaction.
151
+ #
152
+ # TODO: move to dm-more/dm-transaction
153
+ def pop_transaction
154
+ transactions(Thread.current).pop
155
+ end
156
+
157
+ #
158
+ # Retrieve the current transaction for this Adapter.
159
+ #
160
+ # Everything done by this Adapter is done within the context of this
161
+ # Transaction.
162
+ #
163
+ # @return <DataMapper::Transaction> the 'current' transaction for this Adapter.
164
+ #
165
+ # TODO: move to dm-more/dm-transaction
166
+ def current_transaction
167
+ transactions(Thread.current).last
168
+ end
169
+
170
+ #
171
+ # Returns whether we are within a Transaction.
172
+ #
173
+ # @return <Boolean> whether we are within a Transaction.
174
+ #
175
+ # TODO: move to dm-more/dm-transaction
176
+ def within_transaction?
177
+ !current_transaction.nil?
178
+ end
179
+
180
+ #
181
+ # Produces a fresh transaction primitive for this Adapter
182
+ #
183
+ # Used by DataMapper::Transaction to perform its various tasks.
184
+ #
185
+ # @return <Object> a new Object that responds to :close, :begin, :commit,
186
+ # :rollback, :rollback_prepared and :prepare
187
+ #
188
+ # TODO: move to dm-more/dm-transaction (if possible)
189
+ def transaction_primitive
190
+ raise NotImplementedError
191
+ end
192
+
193
+ private
194
+ def transactions(thread)
195
+ unless @transactions[thread]
196
+ @transactions.delete_if do |key, value|
197
+ !key.respond_to?(:alive?) || !key.alive?
198
+ end
199
+ @transactions[thread] = []
200
+ end
201
+ @transactions[thread]
202
+ end
203
+
204
+ end
205
+
206
+ include Transaction
207
+ end # class AbstractAdapter
208
+ end # module Adapters
209
+ end # module DataMapper