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 CHANGED
@@ -71,7 +71,7 @@
71
71
  source 'http://rubygems.org'
72
72
 
73
73
  DATAMAPPER = 'git://github.com/datamapper'
74
- DM_VERSION = '~> 1.0.0.rc3'
74
+ DM_VERSION = '~> 1.0.0'
75
75
 
76
76
  group :runtime do # Runtime dependencies (as in the gemspec)
77
77
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0.rc3
1
+ 1.0.0
@@ -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.rc3"
8
+ s.version = "1.0.0"
9
9
 
10
- s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
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-05-27}
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 = [
@@ -206,7 +206,14 @@ module DataMapper
206
206
 
207
207
  class UpdateConflictError < PersistenceError; end
208
208
 
209
- class SaveFailureError < PersistenceError; end
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
@@ -39,7 +39,8 @@ module DataMapper
39
39
  private
40
40
 
41
41
  def setup_hook(type, name, method, proc)
42
- if types = hooks[name]
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
- types[type] = self.hooks[name][type].map do |command|
58
- command.copy(model)
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
@@ -442,10 +442,10 @@ module DataMapper
442
442
  return true if destroyed?
443
443
  catch :halt do
444
444
  before_destroy_hook
445
- retval = _destroy
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
- # Creates the resource with default values
962
+ # Commit the persisted state
962
963
  #
963
- # If resource is not dirty or a new (not yet saved),
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 _create
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
- retval = _create
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
- retval = _update
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
- deleted = persisted_state.delete
1037
- self.persisted_state = deleted.commit
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
- new_resource ? create_with_hooks : update_with_hooks
1033
+ new? ? create_with_hooks : update_with_hooks
1061
1034
  else
1062
- new_resource ? _create : _update
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, "#{model}##{method} returned #{save_retval.inspect}, #{model} was not saved"
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
- unless model.name.to_s[0] == ?#
21
- parts = model.name.split('::')
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
@@ -1,3 +1,3 @@
1
1
  module DataMapper
2
- VERSION = '1.0.0.rc3'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -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 '.setup' do
5
- it "should not raise with valid models" do
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
- lambda { DataMapper.finalize }.should_not raise_error
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 "should raise on an empty model" do
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
- lambda { DataMapper.finalize }.should raise_error
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 "should raise on a keyless model" do
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
- lambda { DataMapper.finalize }.should raise_error
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(:create) { hooks << :inherited_hook }
103
+ ModelHookSpecs.before(:an_instance_method) { hooks << :inherited_hook }
103
104
  end
104
105
 
105
106
  it 'should execute inherited hook' do
106
- ModelHookSpecsSubclass.create
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(:create) { hooks << :hook }
117
+ ModelHookSpecsSubclass.before(:an_instance_method) { hooks << :hook }
117
118
  end
118
119
 
119
120
  it 'should execute hook' do
120
- ModelHookSpecsSubclass.create
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.create
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: 977940572
5
- prerelease: true
4
+ hash: 23
5
+ prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
9
  - 0
10
- - rc3
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-05-27 00:00:00 -07:00
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: 25
309
+ hash: 3
311
310
  segments:
312
- - 1
313
- - 3
314
- - 1
315
- version: 1.3.1
311
+ - 0
312
+ version: "0"
316
313
  requirements: []
317
314
 
318
315
  rubyforge_project: datamapper