dm-core 1.0.0.rc3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/VERSION +1 -1
- data/dm-core.gemspec +3 -3
- data/lib/dm-core.rb +12 -3
- data/lib/dm-core/model/hook.rb +6 -3
- data/lib/dm-core/resource.rb +18 -44
- data/lib/dm-core/spec/lib/spec_helper.rb +3 -2
- data/lib/dm-core/spec/shared/resource_spec.rb +15 -0
- data/lib/dm-core/version.rb +1 -1
- data/spec/public/finalize_spec.rb +18 -7
- data/spec/public/model/hook_spec.rb +41 -6
- data/spec/public/resource_spec.rb +3 -1
- metadata +8 -11
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.0
|
1
|
+
1.0.0
|
data/dm-core.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dm-core}
|
8
|
-
s.version = "1.0.0
|
8
|
+
s.version = "1.0.0"
|
9
9
|
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Dan Kubb"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-06-08}
|
13
13
|
s.description = %q{Faster, Better, Simpler.}
|
14
14
|
s.email = %q{dan.kubb@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/dm-core.rb
CHANGED
@@ -206,7 +206,14 @@ module DataMapper
|
|
206
206
|
|
207
207
|
class UpdateConflictError < PersistenceError; end
|
208
208
|
|
209
|
-
class SaveFailureError < PersistenceError
|
209
|
+
class SaveFailureError < PersistenceError
|
210
|
+
attr_reader :resource
|
211
|
+
|
212
|
+
def initialize(message, resource)
|
213
|
+
super(message)
|
214
|
+
@resource = resource
|
215
|
+
end
|
216
|
+
end
|
210
217
|
|
211
218
|
class ImmutableError < RuntimeError; end
|
212
219
|
|
@@ -311,6 +318,10 @@ module DataMapper
|
|
311
318
|
repository_name = model.repository_name
|
312
319
|
relationships = model.relationships(repository_name).values
|
313
320
|
|
321
|
+
if name.to_s.strip.empty?
|
322
|
+
raise IncompleteModelError, "#{model.inspect} must have a name"
|
323
|
+
end
|
324
|
+
|
314
325
|
if model.properties(repository_name).empty? &&
|
315
326
|
!relationships.any? { |relationship| relationship.kind_of?(Associations::ManyToOne::Relationship) }
|
316
327
|
raise IncompleteModelError, "#{name} must have at least one property or many to one relationship to be valid"
|
@@ -320,13 +331,11 @@ module DataMapper
|
|
320
331
|
raise IncompleteModelError, "#{name} must have a key to be valid"
|
321
332
|
end
|
322
333
|
|
323
|
-
|
324
334
|
# initialize join models and target keys
|
325
335
|
relationships.each do |relationship|
|
326
336
|
relationship.child_key
|
327
337
|
relationship.through if relationship.respond_to?(:through)
|
328
338
|
relationship.via if relationship.respond_to?(:via)
|
329
339
|
end
|
330
|
-
|
331
340
|
end
|
332
341
|
end
|
data/lib/dm-core/model/hook.rb
CHANGED
@@ -39,7 +39,8 @@ module DataMapper
|
|
39
39
|
private
|
40
40
|
|
41
41
|
def setup_hook(type, name, method, proc)
|
42
|
-
|
42
|
+
types = hooks[name]
|
43
|
+
if types && types[type]
|
43
44
|
types[type] << if proc
|
44
45
|
ProcCommand.new(proc)
|
45
46
|
else
|
@@ -54,8 +55,10 @@ module DataMapper
|
|
54
55
|
def copy_hooks(model)
|
55
56
|
hooks = Hash.new do |hooks, name|
|
56
57
|
hooks[name] = Hash.new do |types, type|
|
57
|
-
|
58
|
-
command
|
58
|
+
if self.hooks[name]
|
59
|
+
types[type] = self.hooks[name][type].map do |command|
|
60
|
+
command.copy(model)
|
61
|
+
end
|
59
62
|
end
|
60
63
|
end
|
61
64
|
end
|
data/lib/dm-core/resource.rb
CHANGED
@@ -442,10 +442,10 @@ module DataMapper
|
|
442
442
|
return true if destroyed?
|
443
443
|
catch :halt do
|
444
444
|
before_destroy_hook
|
445
|
-
|
445
|
+
_destroy
|
446
446
|
after_destroy_hook
|
447
|
-
retval
|
448
447
|
end
|
448
|
+
destroyed?
|
449
449
|
end
|
450
450
|
|
451
451
|
# Destroy the instance, remove it from the repository, bypassing hooks
|
@@ -457,6 +457,7 @@ module DataMapper
|
|
457
457
|
def destroy!
|
458
458
|
return true if destroyed?
|
459
459
|
_destroy(false)
|
460
|
+
destroyed?
|
460
461
|
end
|
461
462
|
|
462
463
|
# Compares another Resource for equality
|
@@ -958,26 +959,13 @@ module DataMapper
|
|
958
959
|
child_relationships.map { |relationship| relationship.get_collection(self) }
|
959
960
|
end
|
960
961
|
|
961
|
-
#
|
962
|
+
# Commit the persisted state
|
962
963
|
#
|
963
|
-
#
|
964
|
-
# this method returns false
|
965
|
-
#
|
966
|
-
# On successful save identity map of the repository is
|
967
|
-
# updated
|
968
|
-
#
|
969
|
-
# Needs to be a protected method so that it is hookable
|
970
|
-
#
|
971
|
-
# The primary purpose of this method is to allow before :create
|
972
|
-
# hooks to fire at a point just before/after resource creation
|
973
|
-
#
|
974
|
-
# @return [Boolean]
|
975
|
-
# true if the receiver was successfully created
|
964
|
+
# @return [undefined]
|
976
965
|
#
|
977
966
|
# @api private
|
978
|
-
def
|
967
|
+
def _persist
|
979
968
|
self.persisted_state = persisted_state.commit
|
980
|
-
true
|
981
969
|
end
|
982
970
|
|
983
971
|
# This method executes the hooks before and after resource creation
|
@@ -991,28 +979,12 @@ module DataMapper
|
|
991
979
|
catch :halt do
|
992
980
|
before_save_hook
|
993
981
|
before_create_hook
|
994
|
-
|
982
|
+
_persist
|
995
983
|
after_create_hook
|
996
984
|
after_save_hook
|
997
|
-
retval
|
998
985
|
end
|
999
986
|
end
|
1000
987
|
|
1001
|
-
# Updates resource state
|
1002
|
-
#
|
1003
|
-
# The primary purpose of this method is to allow before :update
|
1004
|
-
# hooks to fire at a point just before/after resource update whether
|
1005
|
-
# it is the result of Resource#save, or using Resource#update
|
1006
|
-
#
|
1007
|
-
# @return [Boolean]
|
1008
|
-
# true if the receiver was successfully created
|
1009
|
-
#
|
1010
|
-
# @api private
|
1011
|
-
def _update
|
1012
|
-
self.persisted_state = persisted_state.commit
|
1013
|
-
clean?
|
1014
|
-
end
|
1015
|
-
|
1016
988
|
# This method executes the hooks before and after resource updating
|
1017
989
|
#
|
1018
990
|
# @return [Boolean]
|
@@ -1024,18 +996,20 @@ module DataMapper
|
|
1024
996
|
catch :halt do
|
1025
997
|
before_save_hook
|
1026
998
|
before_update_hook
|
1027
|
-
|
999
|
+
_persist
|
1028
1000
|
after_update_hook
|
1029
1001
|
after_save_hook
|
1030
|
-
retval
|
1031
1002
|
end
|
1032
1003
|
end
|
1033
1004
|
|
1005
|
+
# Destroy the resource
|
1006
|
+
#
|
1007
|
+
# @return [undefined]
|
1008
|
+
#
|
1034
1009
|
# @api private
|
1035
1010
|
def _destroy(execute_hooks = true)
|
1036
|
-
|
1037
|
-
|
1038
|
-
true
|
1011
|
+
self.persisted_state = persisted_state.delete
|
1012
|
+
_persist
|
1039
1013
|
end
|
1040
1014
|
|
1041
1015
|
# @api private
|
@@ -1055,12 +1029,12 @@ module DataMapper
|
|
1055
1029
|
# short-circuit if the resource is not dirty
|
1056
1030
|
return saved? unless dirty_self?
|
1057
1031
|
|
1058
|
-
new_resource = new?
|
1059
1032
|
if execute_hooks
|
1060
|
-
|
1033
|
+
new? ? create_with_hooks : update_with_hooks
|
1061
1034
|
else
|
1062
|
-
|
1035
|
+
_persist
|
1063
1036
|
end
|
1037
|
+
clean?
|
1064
1038
|
end
|
1065
1039
|
|
1066
1040
|
# Saves the parent resources
|
@@ -1231,7 +1205,7 @@ module DataMapper
|
|
1231
1205
|
# @api private
|
1232
1206
|
def assert_save_successful(method, save_retval)
|
1233
1207
|
if save_retval != true && raise_on_save_failure
|
1234
|
-
raise SaveFailureError
|
1208
|
+
raise SaveFailureError.new("#{model}##{method} returned #{save_retval.inspect}, #{model} was not saved", self)
|
1235
1209
|
end
|
1236
1210
|
end
|
1237
1211
|
|
@@ -17,8 +17,9 @@ module DataMapper
|
|
17
17
|
while model = descendants.shift
|
18
18
|
descendants.concat(model.descendants.to_a - [ model ])
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
model_name = model.name.to_s.strip
|
21
|
+
unless model_name.empty? || model_name[0] == ?#
|
22
|
+
parts = model_name.split('::')
|
22
23
|
constant_name = parts.pop.to_sym
|
23
24
|
base = parts.empty? ? Object : Object.full_const_get(parts.join('::'))
|
24
25
|
|
@@ -767,6 +767,21 @@ share_examples_for 'A public Resource' do
|
|
767
767
|
end
|
768
768
|
end
|
769
769
|
|
770
|
+
describe 'on a new, invalid resource' do
|
771
|
+
before :all do
|
772
|
+
@user = @user_model.new(:name => nil)
|
773
|
+
@return = @user.__send__(method)
|
774
|
+
end
|
775
|
+
|
776
|
+
it 'should return false' do
|
777
|
+
@return.should be(false)
|
778
|
+
end
|
779
|
+
|
780
|
+
it 'should call save hook expected number of times' do
|
781
|
+
@user.save_hook_call_count.should == (method == :save ? 1 : nil)
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
770
785
|
describe 'on a dirty invalid resource' do
|
771
786
|
before :all do
|
772
787
|
rescue_if @skip do
|
data/lib/dm-core/version.rb
CHANGED
@@ -1,32 +1,43 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
2
|
|
3
3
|
describe DataMapper do
|
4
|
-
describe '.
|
5
|
-
|
4
|
+
describe '.finalize' do
|
5
|
+
subject { DataMapper.finalize }
|
6
|
+
|
7
|
+
it 'should not raise with valid models' do
|
6
8
|
class ::ValidObject
|
7
9
|
include DataMapper::Resource
|
8
10
|
property :id, Integer, :key => true
|
9
11
|
end
|
10
|
-
|
12
|
+
method(:subject).should_not raise_error
|
11
13
|
DataMapper::Model.descendants.delete(ValidObject)
|
12
14
|
Object.send(:remove_const, :ValidObject)
|
13
15
|
end
|
14
16
|
|
15
|
-
it
|
17
|
+
it 'should raise on an anonymous model' do
|
18
|
+
model = Class.new do
|
19
|
+
include DataMapper::Resource
|
20
|
+
property :id, Integer, :key => true
|
21
|
+
end
|
22
|
+
method(:subject).should raise_error(DataMapper::IncompleteModelError, "#{model.inspect} must have a name")
|
23
|
+
DataMapper::Model.descendants.delete(model)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should raise on an empty model' do
|
16
27
|
class ::EmptyObject
|
17
28
|
include DataMapper::Resource
|
18
29
|
end
|
19
|
-
|
30
|
+
method(:subject).should raise_error(DataMapper::IncompleteModelError, 'EmptyObject must have at least one property or many to one relationship to be valid')
|
20
31
|
DataMapper::Model.descendants.delete(EmptyObject)
|
21
32
|
Object.send(:remove_const, :EmptyObject)
|
22
33
|
end
|
23
34
|
|
24
|
-
it
|
35
|
+
it 'should raise on a keyless model' do
|
25
36
|
class ::KeylessObject
|
26
37
|
include DataMapper::Resource
|
27
38
|
property :name, String
|
28
39
|
end
|
29
|
-
|
40
|
+
method(:subject).should raise_error(DataMapper::IncompleteModelError, 'KeylessObject must have a key to be valid')
|
30
41
|
DataMapper::Model.descendants.delete(KeylessObject)
|
31
42
|
Object.send(:remove_const, :KeylessObject)
|
32
43
|
end
|
@@ -12,6 +12,7 @@ describe DataMapper::Model::Hook do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class ::ModelHookSpecsSubclass < ModelHookSpecs; end
|
15
|
+
|
15
16
|
DataMapper.finalize
|
16
17
|
end
|
17
18
|
|
@@ -99,11 +100,11 @@ describe DataMapper::Model::Hook do
|
|
99
100
|
supported_by :all do
|
100
101
|
before do
|
101
102
|
@hooks = hooks = []
|
102
|
-
ModelHookSpecs.before(:
|
103
|
+
ModelHookSpecs.before(:an_instance_method) { hooks << :inherited_hook }
|
103
104
|
end
|
104
105
|
|
105
106
|
it 'should execute inherited hook' do
|
106
|
-
ModelHookSpecsSubclass.
|
107
|
+
ModelHookSpecsSubclass.new.an_instance_method
|
107
108
|
@hooks.should == [ :inherited_hook ]
|
108
109
|
end
|
109
110
|
end
|
@@ -113,22 +114,21 @@ describe DataMapper::Model::Hook do
|
|
113
114
|
supported_by :all do
|
114
115
|
before do
|
115
116
|
@hooks = hooks = []
|
116
|
-
ModelHookSpecsSubclass.before(:
|
117
|
+
ModelHookSpecsSubclass.before(:an_instance_method) { hooks << :hook }
|
117
118
|
end
|
118
119
|
|
119
120
|
it 'should execute hook' do
|
120
|
-
ModelHookSpecsSubclass.
|
121
|
+
ModelHookSpecsSubclass.new.an_instance_method
|
121
122
|
@hooks.should == [ :hook ]
|
122
123
|
end
|
123
124
|
|
124
125
|
it 'should not alter hooks in the parent class' do
|
125
126
|
@hooks.should be_empty
|
126
|
-
ModelHookSpecs.
|
127
|
+
ModelHookSpecs.new.an_instance_method
|
127
128
|
@hooks.should == []
|
128
129
|
end
|
129
130
|
end
|
130
131
|
end
|
131
|
-
|
132
132
|
end
|
133
133
|
|
134
134
|
describe '#after' do
|
@@ -206,5 +206,40 @@ describe DataMapper::Model::Hook do
|
|
206
206
|
end
|
207
207
|
end
|
208
208
|
end
|
209
|
+
|
210
|
+
describe 'with an inherited hook' do
|
211
|
+
supported_by :all do
|
212
|
+
before do
|
213
|
+
@hooks = hooks = []
|
214
|
+
ModelHookSpecs.after(:an_instance_method) { hooks << :inherited_hook }
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'should execute inherited hook' do
|
218
|
+
ModelHookSpecsSubclass.new.an_instance_method
|
219
|
+
@hooks.should == [ :inherited_hook ]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe 'with a hook declared in the subclasss' do
|
225
|
+
supported_by :all do
|
226
|
+
before do
|
227
|
+
@hooks = hooks = []
|
228
|
+
ModelHookSpecsSubclass.after(:an_instance_method) { hooks << :hook }
|
229
|
+
end
|
230
|
+
|
231
|
+
it 'should execute hook' do
|
232
|
+
ModelHookSpecsSubclass.new.an_instance_method
|
233
|
+
@hooks.should == [ :hook ]
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'should not alter hooks in the parent class' do
|
237
|
+
@hooks.should be_empty
|
238
|
+
ModelHookSpecs.new.an_instance_method
|
239
|
+
@hooks.should == []
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
209
244
|
end
|
210
245
|
end
|
@@ -172,7 +172,9 @@ describe DataMapper::Resource do
|
|
172
172
|
end
|
173
173
|
|
174
174
|
it 'should raise an exception' do
|
175
|
-
method(:subject).should raise_error(DataMapper::SaveFailureError, "Blog::User##{method} returned false, Blog::User was not saved")
|
175
|
+
method(:subject).should raise_error(DataMapper::SaveFailureError, "Blog::User##{method} returned false, Blog::User was not saved") { |error|
|
176
|
+
error.resource.should equal(@user)
|
177
|
+
}
|
176
178
|
end
|
177
179
|
end
|
178
180
|
end
|
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dm-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 1
|
8
8
|
- 0
|
9
9
|
- 0
|
10
|
-
|
11
|
-
version: 1.0.0.rc3
|
10
|
+
version: 1.0.0
|
12
11
|
platform: ruby
|
13
12
|
authors:
|
14
13
|
- Dan Kubb
|
@@ -16,7 +15,7 @@ autorequire:
|
|
16
15
|
bindir: bin
|
17
16
|
cert_chain: []
|
18
17
|
|
19
|
-
date: 2010-
|
18
|
+
date: 2010-06-08 00:00:00 -07:00
|
20
19
|
default_executable:
|
21
20
|
dependencies:
|
22
21
|
- !ruby/object:Gem::Dependency
|
@@ -305,14 +304,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
305
304
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
306
305
|
none: false
|
307
306
|
requirements:
|
308
|
-
- - "
|
307
|
+
- - ">="
|
309
308
|
- !ruby/object:Gem::Version
|
310
|
-
hash:
|
309
|
+
hash: 3
|
311
310
|
segments:
|
312
|
-
-
|
313
|
-
|
314
|
-
- 1
|
315
|
-
version: 1.3.1
|
311
|
+
- 0
|
312
|
+
version: "0"
|
316
313
|
requirements: []
|
317
314
|
|
318
315
|
rubyforge_project: datamapper
|