dm-core 1.0.0.rc3 → 1.0.0
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/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
|