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.
- data/.autotest +26 -0
- data/.gitignore +18 -0
- data/CONTRIBUTING +51 -0
- data/FAQ +92 -0
- data/History.txt +52 -0
- data/MIT-LICENSE +22 -0
- data/Manifest.txt +130 -0
- data/QUICKLINKS +11 -0
- data/README.txt +143 -0
- data/Rakefile +32 -0
- data/SPECS +62 -0
- data/TODO +1 -0
- data/dm-core.gemspec +40 -0
- data/lib/dm-core.rb +217 -0
- data/lib/dm-core/adapters.rb +16 -0
- data/lib/dm-core/adapters/abstract_adapter.rb +209 -0
- data/lib/dm-core/adapters/data_objects_adapter.rb +716 -0
- data/lib/dm-core/adapters/in_memory_adapter.rb +87 -0
- data/lib/dm-core/adapters/mysql_adapter.rb +138 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +189 -0
- data/lib/dm-core/adapters/sqlite3_adapter.rb +105 -0
- data/lib/dm-core/associations.rb +207 -0
- data/lib/dm-core/associations/many_to_many.rb +147 -0
- data/lib/dm-core/associations/many_to_one.rb +107 -0
- data/lib/dm-core/associations/one_to_many.rb +315 -0
- data/lib/dm-core/associations/one_to_one.rb +61 -0
- data/lib/dm-core/associations/relationship.rb +221 -0
- data/lib/dm-core/associations/relationship_chain.rb +81 -0
- data/lib/dm-core/auto_migrations.rb +105 -0
- data/lib/dm-core/collection.rb +670 -0
- data/lib/dm-core/dependency_queue.rb +32 -0
- data/lib/dm-core/hook.rb +11 -0
- data/lib/dm-core/identity_map.rb +42 -0
- data/lib/dm-core/is.rb +16 -0
- data/lib/dm-core/logger.rb +232 -0
- data/lib/dm-core/migrations/destructive_migrations.rb +17 -0
- data/lib/dm-core/migrator.rb +29 -0
- data/lib/dm-core/model.rb +526 -0
- data/lib/dm-core/naming_conventions.rb +84 -0
- data/lib/dm-core/property.rb +676 -0
- data/lib/dm-core/property_set.rb +169 -0
- data/lib/dm-core/query.rb +676 -0
- data/lib/dm-core/repository.rb +167 -0
- data/lib/dm-core/resource.rb +671 -0
- data/lib/dm-core/scope.rb +58 -0
- data/lib/dm-core/support.rb +7 -0
- data/lib/dm-core/support/array.rb +13 -0
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/errors.rb +23 -0
- data/lib/dm-core/support/kernel.rb +11 -0
- data/lib/dm-core/support/symbol.rb +41 -0
- data/lib/dm-core/transaction.rb +252 -0
- data/lib/dm-core/type.rb +160 -0
- data/lib/dm-core/type_map.rb +80 -0
- data/lib/dm-core/types.rb +19 -0
- data/lib/dm-core/types/boolean.rb +7 -0
- data/lib/dm-core/types/discriminator.rb +34 -0
- data/lib/dm-core/types/object.rb +24 -0
- data/lib/dm-core/types/paranoid_boolean.rb +34 -0
- data/lib/dm-core/types/paranoid_datetime.rb +33 -0
- data/lib/dm-core/types/serial.rb +9 -0
- data/lib/dm-core/types/text.rb +10 -0
- data/lib/dm-core/version.rb +3 -0
- data/script/all +4 -0
- data/script/performance.rb +282 -0
- data/script/profile.rb +87 -0
- data/spec/integration/association_spec.rb +1382 -0
- data/spec/integration/association_through_spec.rb +203 -0
- data/spec/integration/associations/many_to_many_spec.rb +449 -0
- data/spec/integration/associations/many_to_one_spec.rb +163 -0
- data/spec/integration/associations/one_to_many_spec.rb +188 -0
- data/spec/integration/auto_migrations_spec.rb +413 -0
- data/spec/integration/collection_spec.rb +1073 -0
- data/spec/integration/data_objects_adapter_spec.rb +32 -0
- data/spec/integration/dependency_queue_spec.rb +46 -0
- data/spec/integration/model_spec.rb +197 -0
- data/spec/integration/mysql_adapter_spec.rb +85 -0
- data/spec/integration/postgres_adapter_spec.rb +731 -0
- data/spec/integration/property_spec.rb +253 -0
- data/spec/integration/query_spec.rb +514 -0
- data/spec/integration/repository_spec.rb +61 -0
- data/spec/integration/resource_spec.rb +513 -0
- data/spec/integration/sqlite3_adapter_spec.rb +352 -0
- data/spec/integration/sti_spec.rb +273 -0
- data/spec/integration/strategic_eager_loading_spec.rb +156 -0
- data/spec/integration/transaction_spec.rb +60 -0
- data/spec/integration/type_spec.rb +275 -0
- data/spec/lib/logging_helper.rb +18 -0
- data/spec/lib/mock_adapter.rb +27 -0
- data/spec/lib/model_loader.rb +100 -0
- data/spec/lib/publicize_methods.rb +28 -0
- data/spec/models/content.rb +16 -0
- data/spec/models/vehicles.rb +34 -0
- data/spec/models/zoo.rb +48 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +91 -0
- data/spec/unit/adapters/abstract_adapter_spec.rb +133 -0
- data/spec/unit/adapters/adapter_shared_spec.rb +15 -0
- data/spec/unit/adapters/data_objects_adapter_spec.rb +632 -0
- data/spec/unit/adapters/in_memory_adapter_spec.rb +98 -0
- data/spec/unit/adapters/postgres_adapter_spec.rb +133 -0
- data/spec/unit/associations/many_to_many_spec.rb +32 -0
- data/spec/unit/associations/many_to_one_spec.rb +159 -0
- data/spec/unit/associations/one_to_many_spec.rb +393 -0
- data/spec/unit/associations/one_to_one_spec.rb +7 -0
- data/spec/unit/associations/relationship_spec.rb +71 -0
- data/spec/unit/associations_spec.rb +242 -0
- data/spec/unit/auto_migrations_spec.rb +111 -0
- data/spec/unit/collection_spec.rb +182 -0
- data/spec/unit/data_mapper_spec.rb +35 -0
- data/spec/unit/identity_map_spec.rb +126 -0
- data/spec/unit/is_spec.rb +80 -0
- data/spec/unit/migrator_spec.rb +33 -0
- data/spec/unit/model_spec.rb +321 -0
- data/spec/unit/naming_conventions_spec.rb +36 -0
- data/spec/unit/property_set_spec.rb +90 -0
- data/spec/unit/property_spec.rb +753 -0
- data/spec/unit/query_spec.rb +571 -0
- data/spec/unit/repository_spec.rb +93 -0
- data/spec/unit/resource_spec.rb +649 -0
- data/spec/unit/scope_spec.rb +142 -0
- data/spec/unit/transaction_spec.rb +469 -0
- data/spec/unit/type_map_spec.rb +114 -0
- data/spec/unit/type_spec.rb +119 -0
- data/tasks/ci.rb +36 -0
- data/tasks/dm.rb +63 -0
- data/tasks/doc.rb +20 -0
- data/tasks/gemspec.rb +23 -0
- data/tasks/hoe.rb +46 -0
- data/tasks/install.rb +20 -0
- 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/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
|