datamapper-dm-core 0.9.11 → 0.10.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/.autotest +17 -14
- data/.gitignore +3 -1
- data/FAQ +6 -5
- data/History.txt +5 -39
- data/Manifest.txt +67 -76
- data/QUICKLINKS +1 -1
- data/README.txt +21 -15
- data/Rakefile +16 -15
- data/SPECS +2 -29
- data/TODO +1 -1
- data/dm-core.gemspec +11 -15
- data/lib/dm-core/adapters/abstract_adapter.rb +182 -185
- data/lib/dm-core/adapters/data_objects_adapter.rb +482 -534
- data/lib/dm-core/adapters/in_memory_adapter.rb +90 -69
- data/lib/dm-core/adapters/mysql_adapter.rb +22 -115
- data/lib/dm-core/adapters/oracle_adapter.rb +249 -0
- data/lib/dm-core/adapters/postgres_adapter.rb +7 -173
- data/lib/dm-core/adapters/sqlite3_adapter.rb +4 -97
- data/lib/dm-core/adapters/yaml_adapter.rb +116 -0
- data/lib/dm-core/adapters.rb +135 -16
- data/lib/dm-core/associations/many_to_many.rb +372 -90
- data/lib/dm-core/associations/many_to_one.rb +220 -73
- data/lib/dm-core/associations/one_to_many.rb +319 -255
- data/lib/dm-core/associations/one_to_one.rb +66 -53
- data/lib/dm-core/associations/relationship.rb +560 -158
- data/lib/dm-core/collection.rb +1104 -381
- data/lib/dm-core/core_ext/kernel.rb +12 -0
- data/lib/dm-core/core_ext/symbol.rb +10 -0
- data/lib/dm-core/identity_map.rb +4 -34
- data/lib/dm-core/migrations.rb +1283 -0
- data/lib/dm-core/model/descendant_set.rb +81 -0
- data/lib/dm-core/model/hook.rb +45 -0
- data/lib/dm-core/model/is.rb +32 -0
- data/lib/dm-core/model/property.rb +248 -0
- data/lib/dm-core/model/relationship.rb +335 -0
- data/lib/dm-core/model/scope.rb +90 -0
- data/lib/dm-core/model.rb +570 -369
- data/lib/dm-core/property.rb +753 -280
- data/lib/dm-core/property_set.rb +141 -98
- data/lib/dm-core/query/conditions/comparison.rb +814 -0
- data/lib/dm-core/query/conditions/operation.rb +247 -0
- data/lib/dm-core/query/direction.rb +43 -0
- data/lib/dm-core/query/operator.rb +42 -0
- data/lib/dm-core/query/path.rb +102 -0
- data/lib/dm-core/query/sort.rb +45 -0
- data/lib/dm-core/query.rb +974 -492
- data/lib/dm-core/repository.rb +147 -107
- data/lib/dm-core/resource.rb +644 -429
- data/lib/dm-core/spec/adapter_shared_spec.rb +294 -0
- data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +106 -0
- data/lib/dm-core/support/chainable.rb +20 -0
- data/lib/dm-core/support/deprecate.rb +12 -0
- data/lib/dm-core/support/equalizer.rb +23 -0
- data/lib/dm-core/support/logger.rb +13 -0
- data/lib/dm-core/{naming_conventions.rb → support/naming_conventions.rb} +6 -6
- data/lib/dm-core/transaction.rb +333 -92
- data/lib/dm-core/type.rb +98 -60
- data/lib/dm-core/types/boolean.rb +1 -1
- data/lib/dm-core/types/discriminator.rb +34 -20
- data/lib/dm-core/types/object.rb +7 -4
- data/lib/dm-core/types/paranoid_boolean.rb +11 -9
- data/lib/dm-core/types/paranoid_datetime.rb +11 -9
- data/lib/dm-core/types/serial.rb +3 -3
- data/lib/dm-core/types/text.rb +3 -4
- data/lib/dm-core/version.rb +1 -1
- data/lib/dm-core.rb +106 -110
- data/script/performance.rb +102 -109
- data/script/profile.rb +169 -38
- data/spec/lib/adapter_helpers.rb +105 -0
- data/spec/lib/collection_helpers.rb +18 -0
- data/spec/lib/counter_adapter.rb +34 -0
- data/spec/lib/pending_helpers.rb +27 -0
- data/spec/lib/rspec_immediate_feedback_formatter.rb +53 -0
- data/spec/public/associations/many_to_many_spec.rb +193 -0
- data/spec/public/associations/many_to_one_spec.rb +73 -0
- data/spec/public/associations/one_to_many_spec.rb +77 -0
- data/spec/public/associations/one_to_one_spec.rb +156 -0
- data/spec/public/collection_spec.rb +65 -0
- data/spec/public/model/relationship_spec.rb +924 -0
- data/spec/public/model_spec.rb +159 -0
- data/spec/public/property_spec.rb +829 -0
- data/spec/public/resource_spec.rb +71 -0
- data/spec/public/sel_spec.rb +44 -0
- data/spec/public/setup_spec.rb +145 -0
- data/spec/public/shared/association_collection_shared_spec.rb +317 -0
- data/spec/public/shared/collection_shared_spec.rb +1723 -0
- data/spec/public/shared/finder_shared_spec.rb +1619 -0
- data/spec/public/shared/resource_shared_spec.rb +924 -0
- data/spec/public/shared/sel_shared_spec.rb +112 -0
- data/spec/public/transaction_spec.rb +129 -0
- data/spec/public/types/discriminator_spec.rb +130 -0
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +30 -0
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +12 -0
- data/spec/semipublic/adapters/mysql_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/oracle_adapter_spec.rb +194 -0
- data/spec/semipublic/adapters/postgres_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +17 -0
- data/spec/semipublic/adapters/yaml_adapter_spec.rb +12 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +53 -0
- data/spec/semipublic/associations/relationship_spec.rb +194 -0
- data/spec/semipublic/associations_spec.rb +177 -0
- data/spec/semipublic/collection_spec.rb +142 -0
- data/spec/semipublic/property_spec.rb +61 -0
- data/spec/semipublic/query/conditions_spec.rb +528 -0
- data/spec/semipublic/query/path_spec.rb +443 -0
- data/spec/semipublic/query_spec.rb +2626 -0
- data/spec/semipublic/resource_spec.rb +47 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +126 -0
- data/spec/spec.opts +3 -1
- data/spec/spec_helper.rb +80 -57
- data/tasks/ci.rb +19 -31
- data/tasks/dm.rb +43 -48
- data/tasks/doc.rb +8 -11
- data/tasks/gemspec.rb +5 -5
- data/tasks/hoe.rb +15 -16
- data/tasks/install.rb +8 -10
- metadata +72 -93
- data/lib/dm-core/associations/relationship_chain.rb +0 -81
- data/lib/dm-core/associations.rb +0 -207
- data/lib/dm-core/auto_migrations.rb +0 -105
- data/lib/dm-core/dependency_queue.rb +0 -32
- data/lib/dm-core/hook.rb +0 -11
- data/lib/dm-core/is.rb +0 -16
- data/lib/dm-core/logger.rb +0 -232
- data/lib/dm-core/migrations/destructive_migrations.rb +0 -17
- data/lib/dm-core/migrator.rb +0 -29
- data/lib/dm-core/scope.rb +0 -58
- data/lib/dm-core/support/array.rb +0 -13
- data/lib/dm-core/support/assertions.rb +0 -8
- data/lib/dm-core/support/errors.rb +0 -23
- data/lib/dm-core/support/kernel.rb +0 -11
- data/lib/dm-core/support/symbol.rb +0 -41
- data/lib/dm-core/support.rb +0 -7
- data/lib/dm-core/type_map.rb +0 -80
- data/lib/dm-core/types.rb +0 -19
- data/script/all +0 -4
- data/spec/integration/association_spec.rb +0 -1382
- data/spec/integration/association_through_spec.rb +0 -203
- data/spec/integration/associations/many_to_many_spec.rb +0 -449
- data/spec/integration/associations/many_to_one_spec.rb +0 -163
- data/spec/integration/associations/one_to_many_spec.rb +0 -188
- data/spec/integration/auto_migrations_spec.rb +0 -413
- data/spec/integration/collection_spec.rb +0 -1073
- data/spec/integration/data_objects_adapter_spec.rb +0 -32
- data/spec/integration/dependency_queue_spec.rb +0 -46
- data/spec/integration/model_spec.rb +0 -197
- data/spec/integration/mysql_adapter_spec.rb +0 -85
- data/spec/integration/postgres_adapter_spec.rb +0 -731
- data/spec/integration/property_spec.rb +0 -253
- data/spec/integration/query_spec.rb +0 -514
- data/spec/integration/repository_spec.rb +0 -61
- data/spec/integration/resource_spec.rb +0 -513
- data/spec/integration/sqlite3_adapter_spec.rb +0 -352
- data/spec/integration/sti_spec.rb +0 -273
- data/spec/integration/strategic_eager_loading_spec.rb +0 -156
- data/spec/integration/transaction_spec.rb +0 -75
- data/spec/integration/type_spec.rb +0 -275
- data/spec/lib/logging_helper.rb +0 -18
- data/spec/lib/mock_adapter.rb +0 -27
- data/spec/lib/model_loader.rb +0 -100
- data/spec/lib/publicize_methods.rb +0 -28
- data/spec/models/content.rb +0 -16
- data/spec/models/vehicles.rb +0 -34
- data/spec/models/zoo.rb +0 -48
- data/spec/unit/adapters/abstract_adapter_spec.rb +0 -133
- data/spec/unit/adapters/adapter_shared_spec.rb +0 -15
- data/spec/unit/adapters/data_objects_adapter_spec.rb +0 -632
- data/spec/unit/adapters/in_memory_adapter_spec.rb +0 -98
- data/spec/unit/adapters/postgres_adapter_spec.rb +0 -133
- data/spec/unit/associations/many_to_many_spec.rb +0 -32
- data/spec/unit/associations/many_to_one_spec.rb +0 -159
- data/spec/unit/associations/one_to_many_spec.rb +0 -393
- data/spec/unit/associations/one_to_one_spec.rb +0 -7
- data/spec/unit/associations/relationship_spec.rb +0 -71
- data/spec/unit/associations_spec.rb +0 -242
- data/spec/unit/auto_migrations_spec.rb +0 -111
- data/spec/unit/collection_spec.rb +0 -182
- data/spec/unit/data_mapper_spec.rb +0 -35
- data/spec/unit/identity_map_spec.rb +0 -126
- data/spec/unit/is_spec.rb +0 -80
- data/spec/unit/migrator_spec.rb +0 -33
- data/spec/unit/model_spec.rb +0 -321
- data/spec/unit/naming_conventions_spec.rb +0 -36
- data/spec/unit/property_set_spec.rb +0 -90
- data/spec/unit/property_spec.rb +0 -753
- data/spec/unit/query_spec.rb +0 -571
- data/spec/unit/repository_spec.rb +0 -93
- data/spec/unit/resource_spec.rb +0 -649
- data/spec/unit/scope_spec.rb +0 -142
- data/spec/unit/transaction_spec.rb +0 -493
- data/spec/unit/type_map_spec.rb +0 -114
- data/spec/unit/type_spec.rb +0 -119
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
share_examples_for 'A Collection supporting Strategic Eager Loading' do
|
|
2
|
+
describe 'using SEL when looping within a loop' do
|
|
3
|
+
before :all do
|
|
4
|
+
@many_to_many = @articles.kind_of?(DataMapper::Associations::ManyToMany::Collection)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
before :all do
|
|
8
|
+
attributes = {}
|
|
9
|
+
|
|
10
|
+
unless @many_to_many
|
|
11
|
+
attributes[:author] = @author
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
@revision = @article.revisions.create(attributes.merge(:title => 'Revision'))
|
|
15
|
+
|
|
16
|
+
@new_article = @article_model.create(attributes.merge(:title => 'Sample Article'))
|
|
17
|
+
@new_revision = @new_article.revisions.create(attributes.merge(:title => 'New Revision'))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
before :all do
|
|
21
|
+
@original_adapter = @adapter
|
|
22
|
+
|
|
23
|
+
@adapter.meta_class.class_eval do
|
|
24
|
+
def eql?(other)
|
|
25
|
+
super || self == other
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@adapter = DataMapper::Repository.adapters[@adapter.name] = CounterAdapter.new(@adapter)
|
|
30
|
+
@repository.instance_variable_set(:@adapter, @adapter)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
before :all do
|
|
34
|
+
@results = []
|
|
35
|
+
|
|
36
|
+
@articles.each do |article|
|
|
37
|
+
article.revisions.each do |revision|
|
|
38
|
+
@results << [ article, revision ]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
after :all do
|
|
44
|
+
@adapter = @original_adapter
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should only execute the Adapter#read #{loaded ? 'once' : 'twice'}" do
|
|
48
|
+
@adapter.counts[:read].should == (loaded ? 1 : 2)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'should return the expected results' do
|
|
52
|
+
# if the collection is already loaded, then when it iterates it will
|
|
53
|
+
# not know about the newly added articles and their revisions
|
|
54
|
+
if loaded
|
|
55
|
+
@results.should == [ [ @article, @revision ] ]
|
|
56
|
+
else
|
|
57
|
+
pending_if 'TODO: make m:m not kick when delegating to the relationship', @many_to_many do
|
|
58
|
+
@results.should == [ [ @article, @revision ], [ @new_article, @new_revision ] ]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
share_examples_for 'A Resource supporting Strategic Eager Loading' do
|
|
66
|
+
describe 'using SEL when inside a Collection' do
|
|
67
|
+
before :all do
|
|
68
|
+
@referrer = @user_model.create(:name => 'Referrer', :comment => @comment)
|
|
69
|
+
|
|
70
|
+
@user.update(:referrer => @referrer)
|
|
71
|
+
|
|
72
|
+
@new_user = @user_model.create(:name => 'Another User', :referrer => @referrer, :comment => @comment)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
before :all do
|
|
76
|
+
@original_adapter = @adapter
|
|
77
|
+
|
|
78
|
+
@adapter.meta_class.class_eval do
|
|
79
|
+
def eql?(other)
|
|
80
|
+
super || other == self
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
@adapter = DataMapper::Repository.adapters[@adapter.name] = CounterAdapter.new(@adapter)
|
|
85
|
+
@repository.instance_variable_set(:@adapter, @adapter)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
before :all do
|
|
89
|
+
@results = []
|
|
90
|
+
|
|
91
|
+
@user_model.all.each do |user|
|
|
92
|
+
@results << [ user, user.referrer ]
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# some storage engines return the data in a different order
|
|
96
|
+
@results.sort!
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
after :all do
|
|
100
|
+
@adapter = @original_adapter
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'should only execute the Adapter#read twice' do
|
|
104
|
+
@adapter.counts[:read].should == 2
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'should return the expected results' do
|
|
108
|
+
# results are ordered alphabetically by the User name
|
|
109
|
+
@results.should == [ [ @new_user, @referrer ], [ @referrer, nil ], [ @user, @referrer ] ]
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe DataMapper::Resource, 'Transactions' do
|
|
4
|
+
before :all do
|
|
5
|
+
module ::Blog
|
|
6
|
+
class User
|
|
7
|
+
include DataMapper::Resource
|
|
8
|
+
|
|
9
|
+
property :name, String, :key => true
|
|
10
|
+
property :age, Integer
|
|
11
|
+
property :summary, Text
|
|
12
|
+
property :description, Text
|
|
13
|
+
property :admin, Boolean, :accessor => :private
|
|
14
|
+
|
|
15
|
+
belongs_to :referrer, self, :nullable => true
|
|
16
|
+
has n, :comments
|
|
17
|
+
|
|
18
|
+
# FIXME: figure out a different approach than stubbing things out
|
|
19
|
+
def comment=(*)
|
|
20
|
+
# do nothing with comment
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class Author < User; end
|
|
25
|
+
|
|
26
|
+
class Comment
|
|
27
|
+
include DataMapper::Resource
|
|
28
|
+
|
|
29
|
+
property :id, Serial
|
|
30
|
+
property :body, Text
|
|
31
|
+
|
|
32
|
+
belongs_to :user
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
class Article
|
|
36
|
+
include DataMapper::Resource
|
|
37
|
+
|
|
38
|
+
property :id, Serial
|
|
39
|
+
property :body, Text
|
|
40
|
+
|
|
41
|
+
has n, :paragraphs
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Paragraph
|
|
45
|
+
include DataMapper::Resource
|
|
46
|
+
|
|
47
|
+
property :id, Serial
|
|
48
|
+
property :text, String
|
|
49
|
+
|
|
50
|
+
belongs_to :article
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
@user_model = Blog::User
|
|
55
|
+
@author_model = Blog::Author
|
|
56
|
+
@comment_model = Blog::Comment
|
|
57
|
+
@article_model = Blog::Article
|
|
58
|
+
@paragraph_model = Blog::Paragraph
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
supported_by :postgres, :mysql, :sqlite3, :oracle do
|
|
62
|
+
before :all do
|
|
63
|
+
user = @user_model.create(:name => 'dbussink', :age => 25, :description => 'Test')
|
|
64
|
+
|
|
65
|
+
@user = @user_model.get(*user.key)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
before do
|
|
69
|
+
# --- Temporary private api use to get around rspec limitations ---
|
|
70
|
+
@repository.scope do |repository|
|
|
71
|
+
transaction = DataMapper::Transaction.new(repository)
|
|
72
|
+
transaction.begin
|
|
73
|
+
repository.adapter.push_transaction(transaction)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
after do
|
|
78
|
+
while @repository.adapter.current_transaction
|
|
79
|
+
@repository.adapter.pop_transaction.rollback
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it_should_behave_like 'A public Resource'
|
|
84
|
+
it_should_behave_like 'A Resource supporting Strategic Eager Loading'
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
supported_by :postgres, :mysql, :sqlite3, :oracle do
|
|
88
|
+
describe '#transaction' do
|
|
89
|
+
before do
|
|
90
|
+
@user_model.all.destroy!
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it 'should have access to resources presisted before the transaction' do
|
|
94
|
+
@user_model.create(:name => 'carllerche')
|
|
95
|
+
@user_model.transaction do
|
|
96
|
+
@user_model.first.name.should == 'carllerche'
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it 'should have access to resources persisted in the transaction' do
|
|
101
|
+
@user_model.transaction do
|
|
102
|
+
@user_model.create(:name => 'carllerche')
|
|
103
|
+
@user_model.first.name.should == 'carllerche'
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'should not mark saved resources as new records' do
|
|
108
|
+
@user_model.transaction do
|
|
109
|
+
@user_model.create(:name => 'carllerche').should_not be_new
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'should rollback when an error is thrown in a transaction' do
|
|
114
|
+
@user_model.all.should have(0).entries
|
|
115
|
+
lambda {
|
|
116
|
+
@user_model.transaction do
|
|
117
|
+
@user_model.create(:name => 'carllerche')
|
|
118
|
+
raise 'I love coffee'
|
|
119
|
+
end
|
|
120
|
+
}.should raise_error('I love coffee')
|
|
121
|
+
@user_model.all.should have(0).entries
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'should return the last statement in the transaction block' do
|
|
125
|
+
@user_model.transaction { 1 }.should == 1
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe DataMapper::Types::Discriminator do
|
|
4
|
+
before :all do
|
|
5
|
+
module ::Blog
|
|
6
|
+
class Article
|
|
7
|
+
include DataMapper::Resource
|
|
8
|
+
|
|
9
|
+
property :id, Serial
|
|
10
|
+
property :title, String, :nullable => false
|
|
11
|
+
property :type, Discriminator
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class Announcement < Article; end
|
|
15
|
+
class Release < Announcement; end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
@article_model = Blog::Article
|
|
19
|
+
@announcement_model = Blog::Announcement
|
|
20
|
+
@release_model = Blog::Release
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should typecast to a Model' do
|
|
24
|
+
@article_model.properties[:type].typecast('Blog::Release').should equal(@release_model)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe 'Model#new' do
|
|
28
|
+
describe 'when provided a String discriminator in the attributes' do
|
|
29
|
+
before :all do
|
|
30
|
+
@resource = @article_model.new(:type => 'Blog::Release')
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should return a Resource' do
|
|
34
|
+
@resource.should be_kind_of(DataMapper::Resource)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'should be an descendant instance' do
|
|
38
|
+
@resource.should be_instance_of(Blog::Release)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
describe 'when provided a Class discriminator in the attributes' do
|
|
43
|
+
before :all do
|
|
44
|
+
@resource = @article_model.new(:type => Blog::Release)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it 'should return a Resource' do
|
|
48
|
+
@resource.should be_kind_of(DataMapper::Resource)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it 'should be an descendant instance' do
|
|
52
|
+
@resource.should be_instance_of(Blog::Release)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe 'when not provided a discriminator in the attributes' do
|
|
57
|
+
before :all do
|
|
58
|
+
@resource = @article_model.new
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'should return a Resource' do
|
|
62
|
+
@resource.should be_kind_of(DataMapper::Resource)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'should be a base model instance' do
|
|
66
|
+
@resource.should be_instance_of(@article_model)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe 'Model#descendants' do
|
|
72
|
+
it 'should set the descendants for the grandparent model' do
|
|
73
|
+
@article_model.descendants.to_a.should == [ @article_model, @announcement_model, @release_model ]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'should set the descendants for the parent model' do
|
|
77
|
+
@announcement_model.descendants.to_a.should == [ @announcement_model, @release_model ]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'should set the descendants for the child model' do
|
|
81
|
+
@release_model.descendants.to_a.should == [ @release_model ]
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
describe 'Model#default_scope' do
|
|
86
|
+
it 'should set the default scope for the grandparent model' do
|
|
87
|
+
@article_model.default_scope[:type].should equal(@article_model.descendants)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'should set the default scope for the parent model' do
|
|
91
|
+
@announcement_model.default_scope[:type].should equal(@announcement_model.descendants)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should set the default scope for the child model' do
|
|
95
|
+
@release_model.default_scope[:type].should equal(@release_model.descendants)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
supported_by :all do
|
|
100
|
+
before :all do
|
|
101
|
+
@skip = defined?(DataMapper::Adapters::YamlAdapter) && @adapter.kind_of?(DataMapper::Adapters::YamlAdapter)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
before do
|
|
105
|
+
pending if @skip
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
before :all do
|
|
109
|
+
rescue_if 'TODO: fix YAML serialization/deserialization', @skip do
|
|
110
|
+
@announcement = @announcement_model.create(:title => 'Announcement')
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'should persist the type' do
|
|
115
|
+
@announcement.model.get(*@announcement.key).type.should equal(@announcement_model)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'should be retrieved as an instance of the correct class' do
|
|
119
|
+
@announcement.model.get(*@announcement.key).should be_instance_of(@announcement_model)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
it 'should include descendants in finders' do
|
|
123
|
+
@article_model.first.should eql(@announcement)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it 'should not include ancestors' do
|
|
127
|
+
@release_model.first.should be_nil
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
describe 'AbstractAdapter' do
|
|
4
|
+
before :all do
|
|
5
|
+
@adapter = DataMapper::Adapters::AbstractAdapter.new(:abstract, :foo => 'bar')
|
|
6
|
+
@adapter_class = @adapter.class
|
|
7
|
+
@scheme = Extlib::Inflection.underscore(Extlib::Inflection.demodulize(@adapter_class).chomp('Adapter'))
|
|
8
|
+
@adapter_name = "test_#{@scheme}".to_sym
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe 'initialization' do
|
|
12
|
+
|
|
13
|
+
describe 'name' do
|
|
14
|
+
it 'should have a name' do
|
|
15
|
+
@adapter.name.should == :abstract
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'should set options' do
|
|
20
|
+
@adapter.options.should == {:foo => 'bar'}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should set naming conventions' do
|
|
24
|
+
@adapter.resource_naming_convention.should == DataMapper::NamingConventions::Resource::UnderscoredAndPluralized
|
|
25
|
+
@adapter.field_naming_convention.should == DataMapper::NamingConventions::Field::Underscored
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
require DataMapper.root / 'lib' / 'dm-core' / 'spec' / 'adapter_shared_spec'
|
|
3
|
+
|
|
4
|
+
describe 'Adapter' do
|
|
5
|
+
supported_by :in_memory do
|
|
6
|
+
describe DataMapper::Adapters::InMemoryAdapter do
|
|
7
|
+
|
|
8
|
+
it_should_behave_like 'An Adapter'
|
|
9
|
+
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
dir = DataMapper.root / 'lib' / 'dm-core' / 'spec'
|
|
4
|
+
|
|
5
|
+
require dir / 'adapter_shared_spec'
|
|
6
|
+
require dir / 'data_objects_adapter_shared_spec'
|
|
7
|
+
|
|
8
|
+
describe 'Adapter' do
|
|
9
|
+
supported_by :mysql do
|
|
10
|
+
describe DataMapper::Adapters::MysqlAdapter do
|
|
11
|
+
|
|
12
|
+
it_should_behave_like 'An Adapter'
|
|
13
|
+
it_should_behave_like 'A DataObjects Adapter'
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
dir = DataMapper.root / 'lib' / 'dm-core' / 'spec'
|
|
4
|
+
|
|
5
|
+
require dir / 'adapter_shared_spec'
|
|
6
|
+
require dir / 'data_objects_adapter_shared_spec'
|
|
7
|
+
|
|
8
|
+
module SQLLogHelper
|
|
9
|
+
class SQLLogger
|
|
10
|
+
attr_accessor :buffer
|
|
11
|
+
def initialize
|
|
12
|
+
@buffer = ""
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def level; 0; end
|
|
16
|
+
|
|
17
|
+
def debug(string)
|
|
18
|
+
@buffer << string << "\n"
|
|
19
|
+
# puts "#{string.gsub(/\n/m,"<br/>\n")}<br/>"
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def start_sql_log!
|
|
24
|
+
return if @sql_log_on
|
|
25
|
+
@sql_log_on = true
|
|
26
|
+
@old_logger = DataObjects::Oracle.logger
|
|
27
|
+
DataObjects::Oracle.logger = SQLLogger.new
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def stop_sql_log!
|
|
31
|
+
return unless @sql_log_on
|
|
32
|
+
@sql_log_on = nil
|
|
33
|
+
DataObjects::Oracle.logger = @old_logger
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def clear_sql_log!
|
|
37
|
+
return unless @sql_log_on
|
|
38
|
+
DataObjects::Oracle.logger.buffer = ""
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def sql_log_buffer
|
|
42
|
+
DataObjects::Oracle.logger.buffer
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe 'Adapter' do
|
|
47
|
+
supported_by :oracle do
|
|
48
|
+
describe DataMapper::Adapters::OracleAdapter do
|
|
49
|
+
|
|
50
|
+
it_should_behave_like 'An Adapter'
|
|
51
|
+
it_should_behave_like 'A DataObjects Adapter'
|
|
52
|
+
|
|
53
|
+
describe "sequences" do
|
|
54
|
+
include SQLLogHelper
|
|
55
|
+
|
|
56
|
+
before(:all) do
|
|
57
|
+
@auto_migrate_with = DataMapper::Adapters::OracleAdapter.auto_migrate_with
|
|
58
|
+
DataMapper::Adapters::OracleAdapter.auto_migrate_with :drop_and_create
|
|
59
|
+
start_sql_log!
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
after(:all) do
|
|
63
|
+
stop_sql_log!
|
|
64
|
+
DataMapper::Adapters::OracleAdapter.auto_migrate_with @auto_migrate_with
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "create default sequence and trigger" do
|
|
68
|
+
before(:all) do
|
|
69
|
+
class ::Employee
|
|
70
|
+
include DataMapper::Resource
|
|
71
|
+
property :employee_id, Serial
|
|
72
|
+
end
|
|
73
|
+
Employee.auto_migrate!
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
after(:all) do
|
|
77
|
+
Employee.auto_migrate_down!
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should not have sequence name in options" do
|
|
81
|
+
Employee.properties[:employee_id].options[:sequence].should be_nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should create default sequence" do
|
|
85
|
+
sql_log_buffer.should =~ /CREATE SEQUENCE "EMPLOYEES_SEQ"/
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should create trigger" do
|
|
89
|
+
sql_log_buffer.should =~ /CREATE OR REPLACE TRIGGER "EMPLOYEES_PKT"/
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe "create custom sequence" do
|
|
95
|
+
|
|
96
|
+
before(:all) do
|
|
97
|
+
class ::Employee
|
|
98
|
+
include DataMapper::Resource
|
|
99
|
+
property :employee_id, Serial, :sequence => "emp_seq"
|
|
100
|
+
end
|
|
101
|
+
Employee.auto_migrate!
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
after(:all) do
|
|
105
|
+
Employee.auto_migrate_down!
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should have custom sequence name" do
|
|
109
|
+
Employee.properties[:employee_id].options[:sequence].should == "emp_seq"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "should create custom sequence" do
|
|
113
|
+
sql_log_buffer.should =~ /CREATE SEQUENCE "EMP_SEQ"/
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "should not create trigger" do
|
|
117
|
+
sql_log_buffer.should_not =~ /TRIGGER/
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
describe "create custom sequence in non-default repository" do
|
|
123
|
+
|
|
124
|
+
before(:all) do
|
|
125
|
+
stop_sql_log!
|
|
126
|
+
DataMapper.setup :oracle, DataMapper::Repository.adapters[:default].options
|
|
127
|
+
start_sql_log!
|
|
128
|
+
class ::Employee
|
|
129
|
+
include DataMapper::Resource
|
|
130
|
+
property :id, Serial
|
|
131
|
+
repository(:oracle) do
|
|
132
|
+
property :id, Serial, :field => "employee_id", :sequence => "emp_seq"
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
repository(:oracle) do
|
|
136
|
+
Employee.auto_migrate!
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
after(:all) do
|
|
141
|
+
repository(:oracle) do
|
|
142
|
+
Employee.auto_migrate_down!
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "should have custom sequence name" do
|
|
147
|
+
Employee.properties(:oracle)[:id].options[:sequence].should == "emp_seq"
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
it "should create custom sequence" do
|
|
151
|
+
sql_log_buffer.should =~ /CREATE SEQUENCE "EMP_SEQ"/
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
it "should not create trigger" do
|
|
155
|
+
sql_log_buffer.should_not =~ /TRIGGER/
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
describe "prefetch key value from custom sequence" do
|
|
161
|
+
|
|
162
|
+
before(:all) do
|
|
163
|
+
class ::Employee
|
|
164
|
+
include DataMapper::Resource
|
|
165
|
+
property :employee_id, Serial, :sequence => "emp_seq"
|
|
166
|
+
property :first_name, String
|
|
167
|
+
end
|
|
168
|
+
Employee.auto_migrate!
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
after(:all) do
|
|
172
|
+
Employee.auto_migrate_down!
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "should prefetch sequence value when inserting new record" do
|
|
176
|
+
e = Employee.create
|
|
177
|
+
e.employee_id.should == 1
|
|
178
|
+
e = Employee.create(:first_name => "Raimonds")
|
|
179
|
+
e.employee_id.should == 2
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "should insert explicitly specified primary key value" do
|
|
183
|
+
e = Employee.create(:employee_id => 100,:first_name => "Raimonds")
|
|
184
|
+
e.employee_id.should == 100
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
dir = DataMapper.root / 'lib' / 'dm-core' / 'spec'
|
|
4
|
+
|
|
5
|
+
require dir / 'adapter_shared_spec'
|
|
6
|
+
require dir / 'data_objects_adapter_shared_spec'
|
|
7
|
+
|
|
8
|
+
describe 'Adapter' do
|
|
9
|
+
supported_by :postgres do
|
|
10
|
+
describe DataMapper::Adapters::PostgresAdapter do
|
|
11
|
+
|
|
12
|
+
it_should_behave_like 'An Adapter'
|
|
13
|
+
it_should_behave_like 'A DataObjects Adapter'
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
|
|
3
|
+
dir = DataMapper.root / 'lib' / 'dm-core' / 'spec'
|
|
4
|
+
|
|
5
|
+
require dir / 'adapter_shared_spec'
|
|
6
|
+
require dir / 'data_objects_adapter_shared_spec'
|
|
7
|
+
|
|
8
|
+
describe 'Adapter' do
|
|
9
|
+
supported_by :sqlite3 do
|
|
10
|
+
describe DataMapper::Adapters::Sqlite3Adapter do
|
|
11
|
+
|
|
12
|
+
it_should_behave_like 'An Adapter'
|
|
13
|
+
it_should_behave_like 'A DataObjects Adapter'
|
|
14
|
+
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'spec_helper'))
|
|
2
|
+
require DataMapper.root / 'lib' / 'dm-core' / 'spec' / 'adapter_shared_spec'
|
|
3
|
+
|
|
4
|
+
describe 'Adapter' do
|
|
5
|
+
supported_by :yaml do
|
|
6
|
+
describe DataMapper::Adapters::YamlAdapter do
|
|
7
|
+
|
|
8
|
+
it_should_behave_like 'An Adapter'
|
|
9
|
+
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|