dm-core 0.10.2 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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