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.
- data/.gitignore +10 -1
- data/Gemfile +143 -0
- data/Rakefile +9 -5
- data/VERSION +1 -1
- data/dm-core.gemspec +160 -57
- data/lib/dm-core.rb +131 -56
- data/lib/dm-core/adapters.rb +98 -14
- data/lib/dm-core/adapters/abstract_adapter.rb +24 -4
- data/lib/dm-core/adapters/in_memory_adapter.rb +7 -2
- data/lib/dm-core/associations/many_to_many.rb +19 -30
- data/lib/dm-core/associations/many_to_one.rb +58 -42
- data/lib/dm-core/associations/one_to_many.rb +33 -23
- data/lib/dm-core/associations/one_to_one.rb +27 -11
- data/lib/dm-core/associations/relationship.rb +4 -4
- data/lib/dm-core/collection.rb +23 -16
- data/lib/dm-core/core_ext/array.rb +36 -0
- data/lib/dm-core/core_ext/hash.rb +30 -0
- data/lib/dm-core/core_ext/module.rb +46 -0
- data/lib/dm-core/core_ext/object.rb +31 -0
- data/lib/dm-core/core_ext/pathname.rb +20 -0
- data/lib/dm-core/core_ext/string.rb +22 -0
- data/lib/dm-core/core_ext/try_dup.rb +44 -0
- data/lib/dm-core/model.rb +88 -27
- data/lib/dm-core/model/hook.rb +75 -18
- data/lib/dm-core/model/property.rb +50 -9
- data/lib/dm-core/model/relationship.rb +31 -31
- data/lib/dm-core/model/scope.rb +3 -3
- data/lib/dm-core/property.rb +196 -516
- data/lib/dm-core/property/binary.rb +7 -0
- data/lib/dm-core/property/boolean.rb +35 -0
- data/lib/dm-core/property/class.rb +24 -0
- data/lib/dm-core/property/date.rb +47 -0
- data/lib/dm-core/property/date_time.rb +48 -0
- data/lib/dm-core/property/decimal.rb +43 -0
- data/lib/dm-core/property/discriminator.rb +48 -0
- data/lib/dm-core/property/float.rb +24 -0
- data/lib/dm-core/property/integer.rb +32 -0
- data/lib/dm-core/property/numeric.rb +43 -0
- data/lib/dm-core/property/object.rb +32 -0
- data/lib/dm-core/property/serial.rb +8 -0
- data/lib/dm-core/property/string.rb +49 -0
- data/lib/dm-core/property/text.rb +12 -0
- data/lib/dm-core/property/time.rb +48 -0
- data/lib/dm-core/property/typecast/numeric.rb +32 -0
- data/lib/dm-core/property/typecast/time.rb +28 -0
- data/lib/dm-core/property_set.rb +10 -4
- data/lib/dm-core/query.rb +14 -37
- data/lib/dm-core/query/conditions/comparison.rb +8 -6
- data/lib/dm-core/query/conditions/operation.rb +33 -2
- data/lib/dm-core/query/operator.rb +2 -5
- data/lib/dm-core/query/path.rb +4 -6
- data/lib/dm-core/repository.rb +21 -6
- data/lib/dm-core/resource.rb +316 -133
- data/lib/dm-core/resource/state.rb +79 -0
- data/lib/dm-core/resource/state/clean.rb +40 -0
- data/lib/dm-core/resource/state/deleted.rb +30 -0
- data/lib/dm-core/resource/state/dirty.rb +86 -0
- data/lib/dm-core/resource/state/immutable.rb +34 -0
- data/lib/dm-core/resource/state/persisted.rb +29 -0
- data/lib/dm-core/resource/state/transient.rb +70 -0
- data/lib/dm-core/spec/lib/adapter_helpers.rb +52 -0
- data/lib/dm-core/spec/lib/collection_helpers.rb +20 -0
- data/{spec → lib/dm-core/spec}/lib/counter_adapter.rb +5 -1
- data/lib/dm-core/spec/lib/pending_helpers.rb +50 -0
- data/lib/dm-core/spec/lib/spec_helper.rb +68 -0
- data/lib/dm-core/spec/setup.rb +165 -0
- data/lib/dm-core/spec/{adapter_shared_spec.rb → shared/adapter_spec.rb} +21 -7
- data/{spec/public/shared/resource_shared_spec.rb → lib/dm-core/spec/shared/resource_spec.rb} +120 -83
- data/{spec/public/shared/sel_shared_spec.rb → lib/dm-core/spec/shared/sel_spec.rb} +5 -6
- data/lib/dm-core/support/assertions.rb +8 -0
- data/lib/dm-core/support/equalizer.rb +1 -0
- data/lib/dm-core/support/hook.rb +420 -0
- data/lib/dm-core/support/lazy_array.rb +453 -0
- data/lib/dm-core/support/local_object_space.rb +12 -0
- data/lib/dm-core/support/logger.rb +193 -6
- data/lib/dm-core/support/naming_conventions.rb +8 -8
- data/lib/dm-core/support/subject.rb +33 -0
- data/lib/dm-core/type.rb +4 -0
- data/lib/dm-core/types/boolean.rb +2 -0
- data/lib/dm-core/types/decimal.rb +9 -0
- data/lib/dm-core/types/discriminator.rb +2 -0
- data/lib/dm-core/types/object.rb +3 -0
- data/lib/dm-core/types/serial.rb +2 -0
- data/lib/dm-core/types/text.rb +2 -0
- data/lib/dm-core/version.rb +1 -1
- data/spec/public/associations/many_to_many/read_multiple_join_spec.rb +67 -0
- data/spec/public/model/hook_spec.rb +209 -0
- data/spec/public/model/property_spec.rb +35 -0
- data/spec/public/model/relationship_spec.rb +33 -20
- data/spec/public/model_spec.rb +142 -10
- data/spec/public/property/binary_spec.rb +14 -0
- data/spec/public/property/boolean_spec.rb +14 -0
- data/spec/public/property/class_spec.rb +20 -0
- data/spec/public/property/date_spec.rb +14 -0
- data/spec/public/property/date_time_spec.rb +14 -0
- data/spec/public/property/decimal_spec.rb +14 -0
- data/spec/public/{types → property}/discriminator_spec.rb +2 -12
- data/spec/public/property/float_spec.rb +14 -0
- data/spec/public/property/integer_spec.rb +14 -0
- data/spec/public/property/object_spec.rb +9 -17
- data/spec/public/property/serial_spec.rb +14 -0
- data/spec/public/property/string_spec.rb +14 -0
- data/spec/public/property/text_spec.rb +52 -0
- data/spec/public/property/time_spec.rb +14 -0
- data/spec/public/property_spec.rb +28 -87
- data/spec/public/resource_spec.rb +101 -0
- data/spec/public/sel_spec.rb +5 -15
- data/spec/public/shared/collection_shared_spec.rb +16 -30
- data/spec/public/shared/finder_shared_spec.rb +2 -4
- data/spec/public/shared/property_shared_spec.rb +176 -0
- data/spec/semipublic/adapters/abstract_adapter_spec.rb +1 -1
- data/spec/semipublic/adapters/in_memory_adapter_spec.rb +2 -2
- data/spec/semipublic/associations/many_to_many_spec.rb +89 -0
- data/spec/semipublic/associations/many_to_one_spec.rb +24 -1
- data/spec/semipublic/associations/one_to_many_spec.rb +51 -0
- data/spec/semipublic/associations/one_to_one_spec.rb +49 -0
- data/spec/semipublic/associations/relationship_spec.rb +3 -3
- data/spec/semipublic/associations_spec.rb +1 -1
- data/spec/semipublic/property/binary_spec.rb +13 -0
- data/spec/semipublic/property/boolean_spec.rb +65 -0
- data/spec/semipublic/property/class_spec.rb +33 -0
- data/spec/semipublic/property/date_spec.rb +43 -0
- data/spec/semipublic/property/date_time_spec.rb +46 -0
- data/spec/semipublic/property/decimal_spec.rb +82 -0
- data/spec/semipublic/property/discriminator_spec.rb +19 -0
- data/spec/semipublic/property/float_spec.rb +82 -0
- data/spec/semipublic/property/integer_spec.rb +82 -0
- data/spec/semipublic/property/serial_spec.rb +13 -0
- data/spec/semipublic/property/string_spec.rb +13 -0
- data/spec/semipublic/property/text_spec.rb +31 -0
- data/spec/semipublic/property/time_spec.rb +50 -0
- data/spec/semipublic/property_spec.rb +2 -532
- data/spec/semipublic/query/conditions/comparison_spec.rb +171 -169
- data/spec/semipublic/query/conditions/operation_spec.rb +53 -51
- data/spec/semipublic/query/path_spec.rb +17 -17
- data/spec/semipublic/query_spec.rb +47 -78
- data/spec/semipublic/resource/state/clean_spec.rb +88 -0
- data/spec/semipublic/resource/state/deleted_spec.rb +78 -0
- data/spec/semipublic/resource/state/dirty_spec.rb +133 -0
- data/spec/semipublic/resource/state/immutable_spec.rb +99 -0
- data/spec/semipublic/resource/state/transient_spec.rb +128 -0
- data/spec/semipublic/resource/state_spec.rb +226 -0
- data/spec/semipublic/shared/property_shared_spec.rb +143 -0
- data/spec/semipublic/shared/resource_shared_spec.rb +16 -15
- data/spec/semipublic/shared/resource_state_shared_spec.rb +78 -0
- data/spec/semipublic/shared/subject_shared_spec.rb +79 -0
- data/spec/spec_helper.rb +21 -97
- data/spec/support/types/huge_integer.rb +17 -0
- data/spec/unit/array_spec.rb +48 -0
- data/spec/unit/hash_spec.rb +35 -0
- data/spec/unit/hook_spec.rb +1234 -0
- data/spec/unit/lazy_array_spec.rb +1959 -0
- data/spec/unit/module_spec.rb +70 -0
- data/spec/unit/object_spec.rb +37 -0
- data/spec/unit/try_dup_spec.rb +45 -0
- data/tasks/local_gemfile.rake +18 -0
- data/tasks/spec.rake +0 -3
- metadata +197 -71
- data/deps.rip +0 -2
- data/lib/dm-core/adapters/data_objects_adapter.rb +0 -712
- data/lib/dm-core/adapters/mysql_adapter.rb +0 -42
- data/lib/dm-core/adapters/oracle_adapter.rb +0 -229
- data/lib/dm-core/adapters/postgres_adapter.rb +0 -22
- data/lib/dm-core/adapters/sqlite3_adapter.rb +0 -17
- data/lib/dm-core/adapters/sqlserver_adapter.rb +0 -114
- data/lib/dm-core/adapters/yaml_adapter.rb +0 -111
- data/lib/dm-core/core_ext/enumerable.rb +0 -28
- data/lib/dm-core/migrations.rb +0 -1427
- data/lib/dm-core/spec/data_objects_adapter_shared_spec.rb +0 -366
- data/lib/dm-core/transaction.rb +0 -508
- data/lib/dm-core/types/paranoid_boolean.rb +0 -42
- data/lib/dm-core/types/paranoid_datetime.rb +0 -41
- data/spec/lib/adapter_helpers.rb +0 -105
- data/spec/lib/collection_helpers.rb +0 -18
- data/spec/lib/pending_helpers.rb +0 -46
- data/spec/public/migrations_spec.rb +0 -503
- data/spec/public/transaction_spec.rb +0 -153
- data/spec/semipublic/adapters/mysql_adapter_spec.rb +0 -17
- data/spec/semipublic/adapters/oracle_adapter_spec.rb +0 -194
- data/spec/semipublic/adapters/postgres_adapter_spec.rb +0 -17
- data/spec/semipublic/adapters/sqlite3_adapter_spec.rb +0 -17
- data/spec/semipublic/adapters/sqlserver_adapter_spec.rb +0 -17
- 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
|
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
|
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
|
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
|
167
|
-
|
168
|
-
@user_model.
|
169
|
-
@user_model.
|
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 == @
|
175
|
-
Statistic.new.repository.should == @
|
176
|
-
Statistic.get(statistic.id).repository.should == @
|
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
|
-
@
|
181
|
-
@user_model.new.repository.should == @
|
182
|
-
@user_model.create(:name => 'carl').repository.should == @
|
183
|
-
@user_model.get('carl').repository.should == @
|
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
|
-
@
|
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
|
-
|
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
|
-
|
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
|
-
|
59
|
-
|
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
|
-
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
16
|
+
config.extend( DataMapper::Spec::Adapters::Helpers)
|
17
|
+
config.include(DataMapper::Spec::PendingHelpers)
|
18
|
+
config.include(DataMapper::Spec::Helpers)
|
70
19
|
|
71
|
-
|
72
|
-
|
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
|
-
|
79
|
-
|
80
|
-
|
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
|
-
#
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|