dm-core 0.10.2 → 1.0.0.rc1

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 (183) hide show
  1. data/.gitignore +10 -1
  2. data/Gemfile +143 -0
  3. data/Rakefile +9 -5
  4. data/VERSION +1 -1
  5. data/dm-core.gemspec +160 -57
  6. data/lib/dm-core.rb +131 -56
  7. data/lib/dm-core/adapters.rb +98 -14
  8. data/lib/dm-core/adapters/abstract_adapter.rb +24 -4
  9. data/lib/dm-core/adapters/in_memory_adapter.rb +7 -2
  10. data/lib/dm-core/associations/many_to_many.rb +19 -30
  11. data/lib/dm-core/associations/many_to_one.rb +58 -42
  12. data/lib/dm-core/associations/one_to_many.rb +33 -23
  13. data/lib/dm-core/associations/one_to_one.rb +27 -11
  14. data/lib/dm-core/associations/relationship.rb +4 -4
  15. data/lib/dm-core/collection.rb +23 -16
  16. data/lib/dm-core/core_ext/array.rb +36 -0
  17. data/lib/dm-core/core_ext/hash.rb +30 -0
  18. data/lib/dm-core/core_ext/module.rb +46 -0
  19. data/lib/dm-core/core_ext/object.rb +31 -0
  20. data/lib/dm-core/core_ext/pathname.rb +20 -0
  21. data/lib/dm-core/core_ext/string.rb +22 -0
  22. data/lib/dm-core/core_ext/try_dup.rb +44 -0
  23. data/lib/dm-core/model.rb +88 -27
  24. data/lib/dm-core/model/hook.rb +75 -18
  25. data/lib/dm-core/model/property.rb +50 -9
  26. data/lib/dm-core/model/relationship.rb +31 -31
  27. data/lib/dm-core/model/scope.rb +3 -3
  28. data/lib/dm-core/property.rb +196 -516
  29. data/lib/dm-core/property/binary.rb +7 -0
  30. data/lib/dm-core/property/boolean.rb +35 -0
  31. data/lib/dm-core/property/class.rb +24 -0
  32. data/lib/dm-core/property/date.rb +47 -0
  33. data/lib/dm-core/property/date_time.rb +48 -0
  34. data/lib/dm-core/property/decimal.rb +43 -0
  35. data/lib/dm-core/property/discriminator.rb +48 -0
  36. data/lib/dm-core/property/float.rb +24 -0
  37. data/lib/dm-core/property/integer.rb +32 -0
  38. data/lib/dm-core/property/numeric.rb +43 -0
  39. data/lib/dm-core/property/object.rb +32 -0
  40. data/lib/dm-core/property/serial.rb +8 -0
  41. data/lib/dm-core/property/string.rb +49 -0
  42. data/lib/dm-core/property/text.rb +12 -0
  43. data/lib/dm-core/property/time.rb +48 -0
  44. data/lib/dm-core/property/typecast/numeric.rb +32 -0
  45. data/lib/dm-core/property/typecast/time.rb +28 -0
  46. data/lib/dm-core/property_set.rb +10 -4
  47. data/lib/dm-core/query.rb +14 -37
  48. data/lib/dm-core/query/conditions/comparison.rb +8 -6
  49. data/lib/dm-core/query/conditions/operation.rb +33 -2
  50. data/lib/dm-core/query/operator.rb +2 -5
  51. data/lib/dm-core/query/path.rb +4 -6
  52. data/lib/dm-core/repository.rb +21 -6
  53. data/lib/dm-core/resource.rb +316 -133
  54. data/lib/dm-core/resource/state.rb +79 -0
  55. data/lib/dm-core/resource/state/clean.rb +40 -0
  56. data/lib/dm-core/resource/state/deleted.rb +30 -0
  57. data/lib/dm-core/resource/state/dirty.rb +86 -0
  58. data/lib/dm-core/resource/state/immutable.rb +34 -0
  59. data/lib/dm-core/resource/state/persisted.rb +29 -0
  60. data/lib/dm-core/resource/state/transient.rb +70 -0
  61. data/lib/dm-core/spec/lib/adapter_helpers.rb +52 -0
  62. data/lib/dm-core/spec/lib/collection_helpers.rb +20 -0
  63. data/{spec → lib/dm-core/spec}/lib/counter_adapter.rb +5 -1
  64. data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
  65. data/lib/dm-core/spec/lib/spec_helper.rb +68 -0
  66. data/lib/dm-core/spec/setup.rb +165 -0
  67. data/lib/dm-core/spec/{adapter_shared_spec.rb → shared/adapter_spec.rb} +21 -7
  68. data/{spec/public/shared/resource_shared_spec.rb → lib/dm-core/spec/shared/resource_spec.rb} +120 -83
  69. data/{spec/public/shared/sel_shared_spec.rb → lib/dm-core/spec/shared/sel_spec.rb} +5 -6
  70. data/lib/dm-core/support/assertions.rb +8 -0
  71. data/lib/dm-core/support/equalizer.rb +1 -0
  72. data/lib/dm-core/support/hook.rb +420 -0
  73. data/lib/dm-core/support/lazy_array.rb +453 -0
  74. data/lib/dm-core/support/local_object_space.rb +12 -0
  75. data/lib/dm-core/support/logger.rb +193 -6
  76. data/lib/dm-core/support/naming_conventions.rb +8 -8
  77. data/lib/dm-core/support/subject.rb +33 -0
  78. data/lib/dm-core/type.rb +4 -0
  79. data/lib/dm-core/types/boolean.rb +2 -0
  80. data/lib/dm-core/types/decimal.rb +9 -0
  81. data/lib/dm-core/types/discriminator.rb +2 -0
  82. data/lib/dm-core/types/object.rb +3 -0
  83. data/lib/dm-core/types/serial.rb +2 -0
  84. data/lib/dm-core/types/text.rb +2 -0
  85. data/lib/dm-core/version.rb +1 -1
  86. data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +67 -0
  87. data/spec/public/model/hook_spec.rb +209 -0
  88. data/spec/public/model/property_spec.rb +35 -0
  89. data/spec/public/model/relationship_spec.rb +33 -20
  90. data/spec/public/model_spec.rb +142 -10
  91. data/spec/public/property/binary_spec.rb +14 -0
  92. data/spec/public/property/boolean_spec.rb +14 -0
  93. data/spec/public/property/class_spec.rb +20 -0
  94. data/spec/public/property/date_spec.rb +14 -0
  95. data/spec/public/property/date_time_spec.rb +14 -0
  96. data/spec/public/property/decimal_spec.rb +14 -0
  97. data/spec/public/{types → property}/discriminator_spec.rb +2 -12
  98. data/spec/public/property/float_spec.rb +14 -0
  99. data/spec/public/property/integer_spec.rb +14 -0
  100. data/spec/public/property/object_spec.rb +9 -17
  101. data/spec/public/property/serial_spec.rb +14 -0
  102. data/spec/public/property/string_spec.rb +14 -0
  103. data/spec/public/property/text_spec.rb +52 -0
  104. data/spec/public/property/time_spec.rb +14 -0
  105. data/spec/public/property_spec.rb +28 -87
  106. data/spec/public/resource_spec.rb +101 -0
  107. data/spec/public/sel_spec.rb +5 -15
  108. data/spec/public/shared/collection_shared_spec.rb +16 -30
  109. data/spec/public/shared/finder_shared_spec.rb +2 -4
  110. data/spec/public/shared/property_shared_spec.rb +176 -0
  111. data/spec/semipublic/adapters/abstract_adapter_spec.rb +1 -1
  112. data/spec/semipublic/adapters/in_memory_adapter_spec.rb +2 -2
  113. data/spec/semipublic/associations/many_to_many_spec.rb +89 -0
  114. data/spec/semipublic/associations/many_to_one_spec.rb +24 -1
  115. data/spec/semipublic/associations/one_to_many_spec.rb +51 -0
  116. data/spec/semipublic/associations/one_to_one_spec.rb +49 -0
  117. data/spec/semipublic/associations/relationship_spec.rb +3 -3
  118. data/spec/semipublic/associations_spec.rb +1 -1
  119. data/spec/semipublic/property/binary_spec.rb +13 -0
  120. data/spec/semipublic/property/boolean_spec.rb +65 -0
  121. data/spec/semipublic/property/class_spec.rb +33 -0
  122. data/spec/semipublic/property/date_spec.rb +43 -0
  123. data/spec/semipublic/property/date_time_spec.rb +46 -0
  124. data/spec/semipublic/property/decimal_spec.rb +82 -0
  125. data/spec/semipublic/property/discriminator_spec.rb +19 -0
  126. data/spec/semipublic/property/float_spec.rb +82 -0
  127. data/spec/semipublic/property/integer_spec.rb +82 -0
  128. data/spec/semipublic/property/serial_spec.rb +13 -0
  129. data/spec/semipublic/property/string_spec.rb +13 -0
  130. data/spec/semipublic/property/text_spec.rb +31 -0
  131. data/spec/semipublic/property/time_spec.rb +50 -0
  132. data/spec/semipublic/property_spec.rb +2 -532
  133. data/spec/semipublic/query/conditions/comparison_spec.rb +171 -169
  134. data/spec/semipublic/query/conditions/operation_spec.rb +53 -51
  135. data/spec/semipublic/query/path_spec.rb +17 -17
  136. data/spec/semipublic/query_spec.rb +47 -78
  137. data/spec/semipublic/resource/state/clean_spec.rb +88 -0
  138. data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
  139. data/spec/semipublic/resource/state/dirty_spec.rb +133 -0
  140. data/spec/semipublic/resource/state/immutable_spec.rb +99 -0
  141. data/spec/semipublic/resource/state/transient_spec.rb +128 -0
  142. data/spec/semipublic/resource/state_spec.rb +226 -0
  143. data/spec/semipublic/shared/property_shared_spec.rb +143 -0
  144. data/spec/semipublic/shared/resource_shared_spec.rb +16 -15
  145. data/spec/semipublic/shared/resource_state_shared_spec.rb +78 -0
  146. data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
  147. data/spec/spec_helper.rb +21 -97
  148. data/spec/support/types/huge_integer.rb +17 -0
  149. data/spec/unit/array_spec.rb +48 -0
  150. data/spec/unit/hash_spec.rb +35 -0
  151. data/spec/unit/hook_spec.rb +1234 -0
  152. data/spec/unit/lazy_array_spec.rb +1959 -0
  153. data/spec/unit/module_spec.rb +70 -0
  154. data/spec/unit/object_spec.rb +37 -0
  155. data/spec/unit/try_dup_spec.rb +45 -0
  156. data/tasks/local_gemfile.rake +18 -0
  157. data/tasks/spec.rake +0 -3
  158. metadata +197 -71
  159. data/deps.rip +0 -2
  160. data/lib/dm-core/adapters/data_objects_adapter.rb +0 -712
  161. data/lib/dm-core/adapters/mysql_adapter.rb +0 -42
  162. data/lib/dm-core/adapters/oracle_adapter.rb +0 -229
  163. data/lib/dm-core/adapters/postgres_adapter.rb +0 -22
  164. data/lib/dm-core/adapters/sqlite3_adapter.rb +0 -17
  165. data/lib/dm-core/adapters/sqlserver_adapter.rb +0 -114
  166. data/lib/dm-core/adapters/yaml_adapter.rb +0 -111
  167. data/lib/dm-core/core_ext/enumerable.rb +0 -28
  168. data/lib/dm-core/migrations.rb +0 -1427
  169. data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +0 -366
  170. data/lib/dm-core/transaction.rb +0 -508
  171. data/lib/dm-core/types/paranoid_boolean.rb +0 -42
  172. data/lib/dm-core/types/paranoid_datetime.rb +0 -41
  173. data/spec/lib/adapter_helpers.rb +0 -105
  174. data/spec/lib/collection_helpers.rb +0 -18
  175. data/spec/lib/pending_helpers.rb +0 -46
  176. data/spec/public/migrations_spec.rb +0 -503
  177. data/spec/public/transaction_spec.rb +0 -153
  178. data/spec/semipublic/adapters/mysql_adapter_spec.rb +0 -17
  179. data/spec/semipublic/adapters/oracle_adapter_spec.rb +0 -194
  180. data/spec/semipublic/adapters/postgres_adapter_spec.rb +0 -17
  181. data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +0 -17
  182. data/spec/semipublic/adapters/sqlserver_adapter_spec.rb +0 -17
  183. data/spec/semipublic/adapters/yaml_adapter_spec.rb +0 -12
@@ -0,0 +1,143 @@
1
+ share_examples_for 'A semipublic Property' do
2
+ before :all do
3
+ %w[ @type @name @value @other_value ].each do |ivar|
4
+ raise "+#{ivar}+ should be defined in before block" unless instance_variable_defined?(ivar)
5
+ end
6
+
7
+ module ::Blog
8
+ class Article
9
+ include DataMapper::Resource
10
+ property :id, Serial
11
+ end
12
+ end
13
+
14
+ @model = Blog::Article
15
+ @property = @type.new(@model, @name)
16
+ end
17
+
18
+ describe '.new' do
19
+ describe 'when provided no options' do
20
+ it 'should return a Property' do
21
+ @property.should be_kind_of(@type)
22
+ end
23
+
24
+ it 'should set the primitive' do
25
+ @property.primitive.should be(@type.primitive)
26
+ end
27
+
28
+ it 'should set the model' do
29
+ @property.model.should equal(@model)
30
+ end
31
+
32
+ it 'should set the options to the default' do
33
+ @property.options.should == @type.options
34
+ end
35
+ end
36
+
37
+ [ :index, :unique_index, :unique, :lazy ].each do |attribute|
38
+ [ true, false, :title, [ :title ] ].each do |value|
39
+ describe "when provided #{(options = { attribute => value }).inspect}" do
40
+ before :all do
41
+ @property = @type.new(@model, @name, options)
42
+ end
43
+
44
+ it 'should return a Property' do
45
+ @property.should be_kind_of(@type)
46
+ end
47
+
48
+ it 'should set the model' do
49
+ @property.model.should equal(@model)
50
+ end
51
+
52
+ it 'should set the primitive' do
53
+ @property.primitive.should be(@type.primitive)
54
+ end
55
+
56
+ it "should set the options to #{options.inspect}" do
57
+ @property.options.should == @type.options.merge(options)
58
+ end
59
+ end
60
+ end
61
+
62
+ [ [], nil ].each do |value|
63
+ describe "when provided #{(invalid_options = { attribute => value }).inspect}" do
64
+ it 'should raise an exception' do
65
+ lambda {
66
+ @type.new(@model, @name, invalid_options)
67
+ }.should raise_error(ArgumentError, "options[#{attribute.inspect}] must be either true, false, a Symbol or an Array of Symbols")
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ describe '#load' do
75
+ before :all do
76
+ @value = mock(@value)
77
+ end
78
+
79
+ subject { @property.load(@value) }
80
+
81
+ describe 'with a property' do
82
+ it 'should delegate to #typecast' do
83
+ return_value = mock(@other_value)
84
+ @property.should_receive(:typecast).with(@value).and_return(return_value)
85
+ should == return_value
86
+ end
87
+ end
88
+ end
89
+
90
+ describe '#valid?' do
91
+ describe 'when provided a valid value' do
92
+ it 'should return true' do
93
+ @property.valid?(@value).should be(true)
94
+ end
95
+ end
96
+
97
+ describe 'when provide an invalid value' do
98
+ it 'should return false' do
99
+ @property.valid?(@invalid_value).should be(false)
100
+ end
101
+ end
102
+
103
+ describe 'when provide a nil value when required' do
104
+ it 'should return false' do
105
+ @property = @type.new(@model, @name, :required => true)
106
+ @property.valid?(nil).should be(false)
107
+ end
108
+ end
109
+
110
+ describe 'when provide a nil value when not required' do
111
+ it 'should return false' do
112
+ @property = @type.new(@model, @name, :required => false)
113
+ @property.valid?(nil).should be(true)
114
+ end
115
+ end
116
+ end
117
+
118
+ describe "#typecast" do
119
+ describe "when is able to do typecasting on it's own" do
120
+ it 'delegates all the work to the type' do
121
+ return_value = mock(@other_value)
122
+ @property.should_receive(:typecast_to_primitive).with(@invalid_value).and_return(return_value)
123
+ @property.typecast(@invalid_value)
124
+ end
125
+ end
126
+
127
+ describe 'when value is nil' do
128
+ it 'returns value unchanged' do
129
+ @property.typecast(nil).should be(nil)
130
+ end
131
+
132
+ describe 'when value is a Ruby primitive' do
133
+ it 'returns value unchanged' do
134
+ @property.typecast(@value).should == @value
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ describe '#value' do
141
+ it 'returns value for a core type'
142
+ end
143
+ end
@@ -9,19 +9,19 @@ share_examples_for 'A semipublic Resource' do
9
9
 
10
10
  describe '#attribute_dirty?' do
11
11
  describe 'on a non-dirty record' do
12
- it { @user.attribute_dirty?(:age).should be_false }
12
+ it { @user.attribute_dirty?(:age).should be(false) }
13
13
  end
14
14
 
15
15
  describe 'on a dirty record' do
16
16
  before { @user.age = 100 }
17
17
 
18
- it { @user.attribute_dirty?(:age).should be_true }
18
+ it { @user.attribute_dirty?(:age).should be(true) }
19
19
  end
20
20
 
21
21
  describe 'on a new record' do
22
22
  before { @user = @user_model.new }
23
23
 
24
- it { @user.attribute_dirty?(:age).should be_false }
24
+ it { @user.attribute_dirty?(:age).should be(false) }
25
25
  end
26
26
  end
27
27
 
@@ -163,27 +163,28 @@ share_examples_for 'A semipublic Resource' do
163
163
  end
164
164
 
165
165
  with_alternate_adapter do
166
- it 'should return the default adapter when nothing is specified' do
167
- @user_model.create(:name => 'carl').repository.should == @repository
168
- @user_model.new.repository.should == @repository
169
- @user_model.get('carl').repository.should == @repository
166
+ it 'should return the default repository when nothing is specified' do
167
+ default_repository = DataMapper.repository(:default)
168
+ @user_model.create(:name => 'carl').repository.should == default_repository
169
+ @user_model.new.repository.should == default_repository
170
+ @user_model.get('carl').repository.should == default_repository
170
171
  end
171
172
 
172
173
  it 'should return the default repository for the model' do
173
174
  statistic = Statistic.create(:name => 'visits', :value => 2)
174
- statistic.repository.should == @alternate_repository
175
- Statistic.new.repository.should == @alternate_repository
176
- Statistic.get(statistic.id).repository.should == @alternate_repository
175
+ statistic.repository.should == @repository
176
+ Statistic.new.repository.should == @repository
177
+ Statistic.get(statistic.id).repository.should == @repository
177
178
  end
178
179
 
179
180
  it 'should return the repository defined by the current context' do
180
- @alternate_repository.scope do
181
- @user_model.new.repository.should == @alternate_repository
182
- @user_model.create(:name => 'carl').repository.should == @alternate_repository
183
- @user_model.get('carl').repository.should == @alternate_repository
181
+ @repository.scope do
182
+ @user_model.new.repository.should == @repository
183
+ @user_model.create(:name => 'carl').repository.should == @repository
184
+ @user_model.get('carl').repository.should == @repository
184
185
  end
185
186
 
186
- @alternate_repository.scope { @user_model.get('carl') }.repository.should == @alternate_repository
187
+ @repository.scope { @user_model.get('carl') }.repository.should == @repository
187
188
  end
188
189
  end
189
190
 
@@ -0,0 +1,78 @@
1
+ share_examples_for 'A method that delegates to the superclass #set' do
2
+ it 'should delegate to the superclass' do
3
+ # this is the only way I could think of to test if the
4
+ # superclass method is being called
5
+ DataMapper::Resource::State.class_eval { alias original_set set; undef_method(:set) }
6
+ method(:subject).should raise_error(NoMethodError)
7
+ DataMapper::Resource::State.class_eval { alias set original_set; undef_method(:original_set) }
8
+ end
9
+ end
10
+
11
+ share_examples_for 'A method that does not delegate to the superclass #set' do
12
+ it 'should delegate to the superclass' do
13
+ # this is the only way I could think of to test if the
14
+ # superclass method is not being called
15
+ DataMapper::Resource::State.class_eval { alias original_set set; undef_method(:set) }
16
+ method(:subject).should_not raise_error(NoMethodError)
17
+ DataMapper::Resource::State.class_eval { alias set original_set; undef_method(:original_set) }
18
+ end
19
+ end
20
+
21
+ share_examples_for 'It resets resource state' do
22
+ it 'should reset the dirty property' do
23
+ method(:subject).should change(@resource, :name).from('John Doe').to('Dan Kubb')
24
+ end
25
+
26
+ it 'should reset the dirty m:1 relationship' do
27
+ method(:subject).should change(@resource, :parent).from(@resource).to(nil)
28
+ end
29
+
30
+ it 'should reset the dirty 1:m relationship' do
31
+ method(:subject).should change(@resource, :children).from([ @resource ]).to([])
32
+ end
33
+
34
+ it 'should clear original attributes' do
35
+ method(:subject).should change { @resource.original_attributes.dup }.to({})
36
+ end
37
+ end
38
+
39
+ share_examples_for 'Resource::State::Persisted#get' do
40
+ subject { @state.get(@key) }
41
+
42
+ supported_by :all do
43
+ describe 'with an unloaded subject' do
44
+ before do
45
+ @key = @model.relationships[:parent]
46
+
47
+ # set the parent relationship
48
+ @resource.attributes = { @key => @resource }
49
+ @resource.should be_dirty
50
+ @resource.save.should be(true)
51
+
52
+ @resource = @model.first(@model.key.zip(@resource.key).to_hash.merge(:fields => @model.key))
53
+ @state = @state.class.new(@resource)
54
+
55
+ # make sure the subject is not loaded
56
+ @key.should_not be_loaded(@resource)
57
+ end
58
+
59
+ it 'should lazy load the value' do
60
+ subject.key.should == @resource.key
61
+ end
62
+ end
63
+
64
+ describe 'with a loaded subject' do
65
+ before do
66
+ @key = @model.properties[:name]
67
+ @loaded_value ||= 'Dan Kubb'
68
+
69
+ # make sure the subject is loaded
70
+ @key.should be_loaded(@resource)
71
+ end
72
+
73
+ it 'should return value' do
74
+ should == @loaded_value
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,79 @@
1
+ share_examples_for 'A semipublic Subject' do
2
+ describe '#default?' do
3
+ describe 'with a default' do
4
+ subject { @subject_with_default.default? }
5
+
6
+ it { should be(true) }
7
+ end
8
+
9
+ describe 'without a default' do
10
+ subject { @subject_without_default.default? }
11
+
12
+ it { should be(false) }
13
+ end
14
+ end
15
+
16
+ describe '#default_for' do
17
+ describe 'without a default' do
18
+ subject { @subject_without_default.default_for(@resource) }
19
+
20
+ it 'should match the default value' do
21
+ should be_blank
22
+ end
23
+
24
+ it 'should be used as a default for the subject accessor' do
25
+ should == @resource.__send__(@subject_without_default.name)
26
+ end
27
+
28
+ it 'should persist the value' do
29
+ @resource.save.should be(true)
30
+ @resource = @resource.model.get!(*@resource.key)
31
+ @resource.without_default.should == subject
32
+ end
33
+ end
34
+
35
+ describe 'with a default value' do
36
+ subject { @subject_with_default.default_for(@resource) }
37
+
38
+ it 'should match the default value' do
39
+ if @default_value.kind_of?(DataMapper::Resource)
40
+ subject.key.should == @default_value.key
41
+ else
42
+ should == @default_value
43
+ end
44
+ end
45
+
46
+ it 'should be used as a default for the subject accessor' do
47
+ should == @resource.__send__(@subject_with_default.name)
48
+ end
49
+
50
+ it 'should persist the value' do
51
+ @resource.save.should be(true)
52
+ @resource = @resource.model.get!(*@resource.key)
53
+ @resource.with_default.should == subject
54
+ end
55
+ end
56
+
57
+ describe 'with a default value responding to #call' do
58
+ subject { @subject_with_default_callable.default_for(@resource) }
59
+
60
+ it 'should match the default value' do
61
+ if @default_value.kind_of?(DataMapper::Resource)
62
+ subject.key.should == @default_value_callable.key
63
+ else
64
+ should == @default_value_callable
65
+ end
66
+ end
67
+
68
+ it 'should be used as a default for the subject accessor' do
69
+ should == @resource.__send__(@subject_with_default_callable.name)
70
+ end
71
+
72
+ it 'should persist the value' do
73
+ @resource.save.should be(true)
74
+ @resource = @resource.model.get!(*@resource.key)
75
+ @resource.with_default_callable.should == subject
76
+ end
77
+ end
78
+ end
79
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,115 +1,39 @@
1
1
  require 'pathname'
2
2
  require 'rubygems'
3
-
4
- require 'addressable/uri'
5
3
  require 'spec'
4
+ require 'dm-core/spec/setup'
6
5
 
7
- SPEC_ROOT = Pathname(__FILE__).dirname.expand_path
8
- $LOAD_PATH.unshift(SPEC_ROOT.parent + 'lib')
9
-
10
- require 'dm-core'
11
-
12
- ENV['PLUGINS'].to_s.strip.split(/\s+/).each do |plugin|
13
- require plugin
14
- end
15
-
16
- Pathname.glob((SPEC_ROOT + '{lib,*/shared}/**/*.rb').to_s).each { |file| require file }
17
-
18
- # create sqlite3_fs directory if it doesn't exist
19
- temp_db_dir = SPEC_ROOT.join('db')
20
- temp_db_dir.mkpath
6
+ ENV['ADAPTER'] ||= 'in_memory'
21
7
 
22
- ENV['ADAPTERS'] ||= 'all'
23
-
24
- HAS_DO = DataMapper::Adapters.const_defined?('DataObjectsAdapter')
25
-
26
- ADAPTERS = []
27
-
28
- PRIMARY = {
29
- 'in_memory' => { :adapter => :in_memory },
30
- 'yaml' => "yaml://#{temp_db_dir}/primary_yaml",
31
- 'sqlite3' => 'sqlite3::memory:',
32
- # 'sqlite3_fs' => "sqlite3://#{temp_db_dir}/primary.db",
33
- 'mysql' => 'mysql://localhost/dm_core_test',
34
- 'postgres' => 'postgres://localhost/dm_core_test',
35
- 'oracle' => 'oracle://dm_core_test:dm_core_test@localhost/orcl',
36
- 'sqlserver' => 'sqlserver://dm_core_test:dm_core_test@localhost/dm_core_test;instance=SQLEXPRESS'
37
- }
38
-
39
- ALTERNATE = {
40
- 'in_memory' => { :adapter => :in_memory },
41
- 'yaml' => "yaml://#{temp_db_dir}/secondary_yaml",
42
- 'sqlite3' => "sqlite3://#{temp_db_dir}/alternate.db", # use a FS for the alternate because there can only be one memory db at a time in SQLite3
43
- # 'sqlite3_fs' => "sqlite3://#{temp_db_dir}/alternate.db",
44
- 'mysql' => 'mysql://localhost/dm_core_test2',
45
- 'postgres' => 'postgres://localhost/dm_core_test2',
46
- 'oracle' => 'oracle://dm_core_test2:dm_core_test2@localhost/orcl',
47
- 'sqlserver' => 'sqlserver://dm_core_test:dm_core_test@localhost/dm_core_test2;instance=SQLEXPRESS'
48
- }
49
-
50
- # These environment variables will override the default connection string:
51
- # MYSQL_SPEC_URI
52
- # POSTGRES_SPEC_URI
53
- # SQLITE3_SPEC_URI
54
- #
55
- # For example, in the bash shell, you might use:
56
- # export MYSQL_SPEC_URI="mysql://localhost/dm_core_test?socket=/opt/local/var/run/mysql5/mysqld.sock"
8
+ SPEC_ROOT = Pathname(__FILE__).dirname.expand_path
9
+ LIB_ROOT = SPEC_ROOT.parent + 'lib'
57
10
 
58
- adapters = ENV['ADAPTERS'].split(' ').map { |adapter_name| adapter_name.strip.downcase }.uniq
59
- adapters = PRIMARY.keys if adapters.include?('all')
11
+ Pathname.glob((LIB_ROOT + 'dm-core/spec/**/*.rb' ).to_s).each { |file| require file }
12
+ Pathname.glob((SPEC_ROOT + '{lib,support,*/shared}/**/*.rb').to_s).each { |file| require file }
60
13
 
61
- PRIMARY.only(*adapters).each do |name, default|
62
- connection_string = ENV["#{name.upcase}_SPEC_URI"] || default
63
- begin
64
- adapter = DataMapper.setup(name.to_sym, connection_string)
14
+ Spec::Runner.configure do |config|
65
15
 
66
- # test the connection if possible
67
- if adapter.respond_to?(:query)
68
- name == 'oracle' ? adapter.select('SELECT 1 FROM dual') : adapter.select('SELECT 1')
69
- end
16
+ config.extend( DataMapper::Spec::Adapters::Helpers)
17
+ config.include(DataMapper::Spec::PendingHelpers)
18
+ config.include(DataMapper::Spec::Helpers)
70
19
 
71
- ADAPTERS << name
72
- PRIMARY[name] = connection_string # ensure *_SPEC_URI is saved
73
- rescue Exception => exception
74
- puts "Could not connect to the database using #{connection_string.inspect} because: #{exception.inspect}"
20
+ config.after :all do
21
+ DataMapper::Spec.cleanup_models
75
22
  end
76
- end
77
23
 
78
- # speed up test execution on Oracle
79
- if defined?(DataMapper::Adapters::OracleAdapter)
80
- DataMapper::Adapters::OracleAdapter.instance_eval do
81
- auto_migrate_with :delete # table data will be deleted instead of dropping and creating table
82
- auto_migrate_reset_sequences false # primary key sequences will not be reset
24
+ config.after :all do
25
+ # global ivar cleanup
26
+ DataMapper::Spec.remove_ivars(self, instance_variables.reject { |ivar| ivar[0, 2] == '@_' })
83
27
  end
84
- end
85
-
86
- ADAPTERS.freeze
87
- PRIMARY.freeze
88
-
89
- logger = DataMapper::Logger.new(DataMapper.root / 'log' / 'dm.log', :debug)
90
- logger.auto_flush = true
91
-
92
- Spec::Runner.configure do |config|
93
- config.extend(DataMapper::Spec::AdapterHelpers)
94
- config.include(DataMapper::Spec::PendingHelpers)
95
28
 
96
29
  config.after :all do
97
- # global model cleanup
98
- descendants = DataMapper::Model.descendants.to_a
99
- while model = descendants.shift
100
- descendants.concat(model.descendants.to_a - [ model ])
101
-
102
- parts = model.name.split('::')
103
- constant_name = parts.pop.to_sym
104
- base = parts.empty? ? Object : Object.full_const_get(parts.join('::'))
105
-
106
- if base.const_defined?(constant_name)
107
- base.send(:remove_const, constant_name)
108
- end
109
-
110
- DataMapper::Model.descendants.delete(model)
111
- end
30
+ # WTF: rspec holds a reference to the last match for some reason.
31
+ # When the object ivars are explicitly removed, this causes weird
32
+ # problems when rspec uses it (!). Why rspec does this I have no
33
+ # idea because I cannot determine the intention from the code.
34
+ DataMapper::Spec.remove_ivars(Spec::Matchers.last_matcher, %w[ @expected ])
112
35
  end
36
+
113
37
  end
114
38
 
115
39
  # remove the Resource#send method to ensure specs/internals do no rely on it