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
@@ -0,0 +1,35 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe DataMapper do
4
+ describe ".dependency_queue" do
5
+ before(:all) do
6
+ @q = DataMapper.dependency_queue
7
+ end
8
+
9
+ it "should return a dependency queue" do
10
+ @q.should be_a_kind_of(DataMapper::DependencyQueue)
11
+ end
12
+
13
+ it "should only create one dependency queue" do
14
+ @q.should == DataMapper.dependency_queue
15
+ end
16
+ end
17
+
18
+ describe ".prepare" do
19
+ it "should pass the default repository to the block if no argument is given" do
20
+ DataMapper.should_receive(:repository).with(no_args).and_return :default_repo
21
+
22
+ DataMapper.prepare do |r|
23
+ r.should == :default_repo
24
+ end
25
+ end
26
+
27
+ it "should allow custom type maps to be defined inside the prepare block" do
28
+ lambda {
29
+ DataMapper.prepare do |r|
30
+ r.map(String).to(:VARCHAR).with(:size => 1000)
31
+ end
32
+ }.should_not raise_error
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,126 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe "DataMapper::IdentityMap" do
4
+ before(:all) do
5
+ class ::Cow
6
+ include DataMapper::Resource
7
+ property :id, Integer, :key => true
8
+ property :name, String
9
+ end
10
+
11
+ class ::Chicken
12
+ include DataMapper::Resource
13
+ property :name, String
14
+ end
15
+
16
+ class ::Pig
17
+ include DataMapper::Resource
18
+ property :id, Integer, :key => true
19
+ property :composite, Integer, :key => true
20
+ property :name, String
21
+ end
22
+ end
23
+
24
+ it "should use a second level cache if created with on"
25
+
26
+ it "should return nil on #get when it does not find the requested instance" do
27
+ map = DataMapper::IdentityMap.new
28
+ map.get([23]).should be_nil
29
+ end
30
+
31
+ it "should return an instance on #get when it finds the requested instance" do
32
+ betsy = Cow.new({:id=>23,:name=>'Betsy'})
33
+ map = DataMapper::IdentityMap.new
34
+ map.set(betsy.key, betsy)
35
+ map.get([23]).should == betsy
36
+ end
37
+
38
+ it "should store an instance on #set" do
39
+ betsy = Cow.new({:id=>23,:name=>'Betsy'})
40
+ map = DataMapper::IdentityMap.new
41
+ map.set(betsy.key, betsy)
42
+ map.get([23]).should == betsy
43
+ end
44
+
45
+ it "should store instances with composite keys on #set" do
46
+ pig = Pig.new({:id=>1,:composite=>1,:name=> 'Pig'})
47
+ piggy = Pig.new({:id=>1,:composite=>2,:name=>'Piggy'})
48
+
49
+ map = DataMapper::IdentityMap.new
50
+ map.set(pig.key, pig)
51
+ map.set(piggy.key, piggy)
52
+
53
+ map.get([1,1]).should == pig
54
+ map.get([1,2]).should == piggy
55
+ end
56
+
57
+ it "should remove an instance on #delete" do
58
+ betsy = Cow.new({:id=>23,:name=>'Betsy'})
59
+ map = DataMapper::IdentityMap.new
60
+ map.set(betsy.key, betsy)
61
+ map.delete([23])
62
+ map.get([23]).should be_nil
63
+ end
64
+ end
65
+
66
+ describe "Second Level Caching" do
67
+
68
+ before :all do
69
+ @mock_class = Class.new do
70
+ def get(key); raise NotImplementedError end
71
+ def set(key, instance); raise NotImplementedError end
72
+ def delete(key); raise NotImplementedError end
73
+ end
74
+ end
75
+
76
+ it 'should expose a standard API' do
77
+ cache = @mock_class.new
78
+ cache.should respond_to(:get)
79
+ cache.should respond_to(:set)
80
+ cache.should respond_to(:delete)
81
+ end
82
+
83
+ it 'should provide values when the first level cache entry is empty' do
84
+ cache = @mock_class.new
85
+ key = %w[ test ]
86
+
87
+ cache.should_receive(:get).with(key).and_return('resource')
88
+
89
+ map = DataMapper::IdentityMap.new(cache)
90
+ map.get(key).should == 'resource'
91
+ end
92
+
93
+ it 'should be set when the first level cache entry is set' do
94
+ cache = @mock_class.new
95
+ betsy = Cow.new(:id => 23, :name => 'Betsy')
96
+
97
+ cache.should_receive(:set).with(betsy.key, betsy).and_return(betsy)
98
+
99
+ map = DataMapper::IdentityMap.new(cache)
100
+ map.set(betsy.key, betsy).should == betsy
101
+ end
102
+
103
+ it 'should be deleted when the first level cache entry is deleted' do
104
+ cache = @mock_class.new
105
+ betsy = Cow.new(:id => 23, :name => 'Betsy')
106
+
107
+ cache.stub!(:set)
108
+ cache.should_receive(:delete).with(betsy.key).and_return(betsy)
109
+
110
+ map = DataMapper::IdentityMap.new(cache)
111
+ map.set(betsy.key, betsy).should == betsy
112
+ map.delete(betsy.key).should == betsy
113
+ end
114
+
115
+ it 'should not provide values when the first level cache entry is full' do
116
+ cache = @mock_class.new
117
+ betsy = Cow.new(:id => 23, :name => 'Betsy')
118
+
119
+ cache.stub!(:set)
120
+ cache.should_not_receive(:get)
121
+
122
+ map = DataMapper::IdentityMap.new(cache)
123
+ map.set(betsy.key, betsy).should == betsy
124
+ map.get(betsy.key).should == betsy
125
+ end
126
+ end
@@ -0,0 +1,80 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe "DataMapper::Is" do
4
+ describe ".is" do
5
+
6
+ module ::DataMapper
7
+
8
+ module Is
9
+ module Example
10
+
11
+ def is_example(*args)
12
+ @args = args
13
+
14
+ extend DataMapper::Is::Example::ClassMethods
15
+ end
16
+
17
+ def is_example_args
18
+ @args
19
+ end
20
+
21
+ module ClassMethods
22
+ def example_class_method
23
+
24
+ end
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ module Model
31
+ include DataMapper::Is::Example
32
+ end # module Model
33
+ end # module DataMapper
34
+
35
+ class ::House
36
+ include DataMapper::Resource
37
+ end
38
+
39
+ class ::Cabin
40
+ include DataMapper::Resource
41
+ end
42
+
43
+ it "should raise error unless it finds the plugin" do
44
+ lambda do
45
+ class ::House
46
+ is :no_plugin_by_this_name
47
+ end
48
+ end.should raise_error(DataMapper::PluginNotFoundError)
49
+ end
50
+
51
+ it "should call plugin is_* method" do
52
+ lambda do
53
+ class ::House
54
+ is :example
55
+ end
56
+ end.should_not raise_error
57
+ end
58
+
59
+ it "should pass through arguments to plugin is_* method" do
60
+ class ::House
61
+ is :example ,:option1 => :ping, :option2 => :pong
62
+ end
63
+
64
+ House.is_example_args.length.should == 1
65
+ House.is_example_args.first[:option2].should == :pong
66
+ end
67
+
68
+ it "should not add class_methods before the plugin is activated" do
69
+ Cabin.respond_to?(:example_class_method).should be_false
70
+
71
+ class ::Cabin
72
+ is :example
73
+ end
74
+
75
+ Cabin.respond_to?(:example_class_method).should be_true
76
+
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,33 @@
1
+ require 'pathname'
2
+ require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
3
+
4
+ describe DataMapper::Migrator do
5
+ before(:each) do
6
+ DataMapper::Migrator.subclasses.clear
7
+ end
8
+
9
+ after(:each) do
10
+ DataMapper::Migrator.subclasses.clear
11
+ end
12
+
13
+ it "should keep track of subclasses" do
14
+ lambda { Class.new(DataMapper::Migrator) }.should change{ DataMapper::Migrator.subclasses.size }.by(1)
15
+ end
16
+
17
+ it "should define a class level 'models' method for each subclass" do
18
+ klass = Class.new(DataMapper::Migrator)
19
+
20
+ klass.should respond_to(:models)
21
+ end
22
+
23
+ it "should keep subclass models seperated" do
24
+ klass_a = Class.new(DataMapper::Migrator)
25
+ klass_b = Class.new(DataMapper::Migrator)
26
+
27
+ klass_a.models << :foo
28
+
29
+ klass_b.models.should be_empty
30
+
31
+ klass_a.models.should == [:foo]
32
+ end
33
+ end
@@ -0,0 +1,321 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
2
+
3
+ describe 'DataMapper::Model' do
4
+ before do
5
+ Object.send(:remove_const, :ModelSpec) if defined?(ModelSpec)
6
+ module ModelSpec
7
+ class Resource
8
+ include DataMapper::Resource
9
+
10
+ storage_names[:legacy] = 'legacy_resource'
11
+
12
+ property :id, Serial
13
+ property :name, String
14
+ property :type, Discriminator
15
+ end
16
+ end
17
+ end
18
+
19
+ it 'should provide .new' do
20
+ meta_class = class << ModelSpec::Resource; self end
21
+ meta_class.should respond_to(:new)
22
+ end
23
+
24
+ describe '.new' do
25
+ it 'should require a default storage name and accept a block' do
26
+ pluto = DataMapper::Model.new('planets') do
27
+ property :name, String, :key => true
28
+ end
29
+
30
+ pluto.storage_name(:default).should == 'planets'
31
+ pluto.storage_name(:legacy).should == 'planets'
32
+ pluto.properties[:name].should_not be_nil
33
+ end
34
+ end
35
+
36
+ it 'should provide #transaction' do
37
+ ModelSpec::Resource.should respond_to(:transaction)
38
+ end
39
+
40
+ describe '#transaction' do
41
+ it 'should return a new Transaction with Model as argument' do
42
+ transaction = mock("transaction")
43
+ DataMapper::Transaction.should_receive(:new).with(ModelSpec::Resource).and_return(transaction)
44
+ ModelSpec::Resource.transaction.should == transaction
45
+ end
46
+ end
47
+
48
+ it 'should provide #before' do
49
+ ModelSpec::Resource.should respond_to(:before)
50
+ end
51
+
52
+ it 'should provide #after' do
53
+ ModelSpec::Resource.should respond_to(:after)
54
+ end
55
+
56
+ it 'should provide #repository' do
57
+ ModelSpec::Resource.should respond_to(:repository)
58
+ end
59
+
60
+ describe '#repository' do
61
+ it 'should delegate to DataMapper.repository' do
62
+ repository = mock('repository')
63
+ DataMapper.should_receive(:repository).with(:legacy).and_return(repository)
64
+ ModelSpec::Resource.repository(:legacy).should == repository
65
+ end
66
+
67
+ it 'should use default repository when not passed any arguments' do
68
+ ModelSpec::Resource.repository.name.should == ModelSpec::Resource.repository(:default).name
69
+ end
70
+ end
71
+
72
+ it 'should provide #storage_name' do
73
+ ModelSpec::Resource.should respond_to(:storage_name)
74
+ end
75
+
76
+ describe '#storage_name' do
77
+ it 'should map a repository to the storage location' do
78
+ ModelSpec::Resource.storage_name(:legacy).should == 'legacy_resource'
79
+ end
80
+
81
+ it 'should use default repository when not passed any arguments' do
82
+ ModelSpec::Resource.storage_name.object_id.should == ModelSpec::Resource.storage_name(:default).object_id
83
+ end
84
+ end
85
+
86
+ it 'should provide #storage_names' do
87
+ ModelSpec::Resource.should respond_to(:storage_names)
88
+ end
89
+
90
+ describe '#storage_names' do
91
+ it 'should return a Hash mapping each repository to a storage location' do
92
+ ModelSpec::Resource.storage_names.should be_kind_of(Hash)
93
+ ModelSpec::Resource.storage_names.should == { :legacy => 'legacy_resource' }
94
+ end
95
+ end
96
+
97
+ it 'should provide #property' do
98
+ ModelSpec::Resource.should respond_to(:property)
99
+ end
100
+
101
+ describe '#property' do
102
+ it 'should raise a SyntaxError when the name contains invalid characters' do
103
+ lambda {
104
+ ModelSpec::Resource.property(:"with space", TrueClass)
105
+ }.should raise_error(SyntaxError)
106
+ end
107
+ end
108
+
109
+ it 'should provide #properties' do
110
+ ModelSpec::Resource.should respond_to(:properties)
111
+ end
112
+
113
+ describe '#properties' do
114
+ it 'should return an PropertySet' do
115
+ ModelSpec::Resource.properties(:legacy).should be_kind_of(DataMapper::PropertySet)
116
+ ModelSpec::Resource.properties(:legacy).should have(3).entries
117
+ end
118
+
119
+ it 'should use default repository when not passed any arguments' do
120
+ ModelSpec::Resource.properties.object_id.should == ModelSpec::Resource.properties(:default).object_id
121
+ end
122
+ end
123
+
124
+ it 'should provide #key' do
125
+ ModelSpec::Resource.should respond_to(:key)
126
+ end
127
+
128
+ describe '#key' do
129
+ it 'should return an Array of Property objects' do
130
+ ModelSpec::Resource.key(:legacy).should be_kind_of(Array)
131
+ ModelSpec::Resource.key(:legacy).should have(1).entries
132
+ ModelSpec::Resource.key(:legacy).first.should be_kind_of(DataMapper::Property)
133
+ end
134
+
135
+ it 'should use default repository when not passed any arguments' do
136
+ ModelSpec::Resource.key.should == ModelSpec::Resource.key(:default)
137
+ end
138
+
139
+ it 'should not cache the key value' do
140
+ class GasGiant < ModelSpec::Resource
141
+ end
142
+
143
+ GasGiant.key.object_id.should_not == ModelSpec::Resource.key(:default)
144
+
145
+ # change the key and make sure the Array changes
146
+ GasGiant.key == GasGiant.properties.slice(:id)
147
+ GasGiant.property(:new_prop, String, :key => true)
148
+ GasGiant.key.object_id.should_not == ModelSpec::Resource.key(:default)
149
+ GasGiant.key == GasGiant.properties.slice(:id, :new_prop)
150
+ end
151
+ end
152
+
153
+ it 'should provide #get' do
154
+ ModelSpec::Resource.should respond_to(:get)
155
+ end
156
+
157
+ it 'should provide #first' do
158
+ ModelSpec::Resource.should respond_to(:first)
159
+ end
160
+
161
+ it 'should provide #all' do
162
+ ModelSpec::Resource.should respond_to(:all)
163
+ end
164
+
165
+ it 'should provide #storage_exists?' do
166
+ ModelSpec::Resource.should respond_to(:storage_exists?)
167
+ end
168
+
169
+ describe '#storage_exists?' do
170
+ it 'should return whether or not the storage exists' do
171
+ ModelSpec::Resource.storage_exists?.should == false
172
+ end
173
+ end
174
+
175
+ it 'should provide #default_order' do
176
+ ModelSpec::Resource.should respond_to(:default_order)
177
+ end
178
+
179
+ describe '#default_order' do
180
+ it 'should be equal to #key by default' do
181
+ ModelSpec::Resource.default_order.should == [ DataMapper::Query::Direction.new(ModelSpec::Resource.properties[:id], :asc) ]
182
+ end
183
+ end
184
+
185
+ describe '#append_inclusions' do
186
+ before(:all) do
187
+ @standard_resource_inclusions = DataMapper::Resource.instance_variable_get('@extra_inclusions')
188
+ @standard_model_extensions = DataMapper::Model.instance_variable_get('@extra_extensions')
189
+ end
190
+
191
+ before(:each) do
192
+ DataMapper::Resource.instance_variable_set('@extra_inclusions', [])
193
+ DataMapper::Model.instance_variable_set('@extra_extensions', [])
194
+
195
+ @module = Module.new do
196
+ def greet
197
+ hi_mom!
198
+ end
199
+ end
200
+
201
+ @another_module = Module.new do
202
+ def hello
203
+ hi_dad!
204
+ end
205
+ end
206
+
207
+ @class = Class.new
208
+
209
+ @class_code = %{
210
+ include DataMapper::Resource
211
+ property :id, Serial
212
+ }
213
+ end
214
+
215
+ after(:each) do
216
+ DataMapper::Resource.instance_variable_set('@extra_inclusions', @standard_resource_inclusions)
217
+ DataMapper::Model.instance_variable_set('@extra_extensions', @standard_model_extensions)
218
+ end
219
+
220
+ it "should append the module to be included in resources" do
221
+ DataMapper::Resource.append_inclusions @module
222
+ @class.class_eval(@class_code)
223
+
224
+ instance = @class.new
225
+ instance.should_receive(:hi_mom!)
226
+ instance.greet
227
+ end
228
+
229
+ it "should append the module to all resources" do
230
+ DataMapper::Resource.append_inclusions @module
231
+
232
+ objects = (1..5).map do
233
+ the_class = Class.new
234
+ the_class.class_eval(@class_code)
235
+
236
+ instance = the_class.new
237
+ instance.should_receive(:hi_mom!)
238
+ instance
239
+ end
240
+
241
+ objects.each { |obj| obj.greet }
242
+ end
243
+
244
+ it "should append multiple modules to be included in resources" do
245
+ DataMapper::Resource.append_inclusions @module, @another_module
246
+ @class.class_eval(@class_code)
247
+
248
+ instance = @class.new
249
+ instance.should_receive(:hi_mom!)
250
+ instance.should_receive(:hi_dad!)
251
+ instance.greet
252
+ instance.hello
253
+ end
254
+
255
+ it "should include the appended modules in order" do
256
+ module_one = Module.new do
257
+ def self.included(base); base.hi_mom!; end;
258
+ end
259
+
260
+ module_two = Module.new do
261
+ def self.included(base); base.hi_dad!; end;
262
+ end
263
+
264
+ DataMapper::Resource.append_inclusions module_two, module_one
265
+
266
+ @class.should_receive(:hi_dad!).once.ordered
267
+ @class.should_receive(:hi_mom!).once.ordered
268
+
269
+ @class.class_eval(@class_code)
270
+ end
271
+
272
+ it "should append the module to extend resources with" do
273
+ DataMapper::Model.append_extensions @module
274
+ @class.class_eval(@class_code)
275
+
276
+ @class.should_receive(:hi_mom!)
277
+ @class.greet
278
+ end
279
+
280
+ it "should extend all resources with the module" do
281
+ DataMapper::Model.append_extensions @module
282
+
283
+ classes = (1..5).map do
284
+ the_class = Class.new
285
+ the_class.class_eval(@class_code)
286
+ the_class.should_receive(:hi_mom!)
287
+ the_class
288
+ end
289
+
290
+ classes.each { |cla| cla.greet }
291
+ end
292
+
293
+ it "should append multiple modules to extend resources with" do
294
+ DataMapper::Model.append_extensions @module, @another_module
295
+ @class.class_eval(@class_code)
296
+
297
+ @class.should_receive(:hi_mom!)
298
+ @class.should_receive(:hi_dad!)
299
+ @class.greet
300
+ @class.hello
301
+ end
302
+
303
+ it "should extend the resource in the order that the modules were appended" do
304
+ @module.class_eval do
305
+ def self.extended(base); base.hi_mom!; end;
306
+ end
307
+
308
+ @another_module.class_eval do
309
+ def self.extended(base); base.hi_dad!; end;
310
+ end
311
+
312
+ DataMapper::Model.append_extensions @another_module, @module
313
+
314
+ @class.should_receive(:hi_dad!).once.ordered
315
+ @class.should_receive(:hi_mom!).once.ordered
316
+
317
+ @class.class_eval(@class_code)
318
+ end
319
+
320
+ end
321
+ end