m4dbi 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/m4dbi/model.rb CHANGED
@@ -2,7 +2,7 @@ module M4DBI
2
2
  class Model
3
3
  #attr_reader :row
4
4
  ancestral_trait_reader :dbh, :table
5
- ancestral_trait_class_reader :dbh, :table, :pk, :columns, :st
5
+ ancestral_trait_class_reader :dbh, :table, :pk, :columns, :st, :callbacks
6
6
 
7
7
  M4DBI_UNASSIGNED = '__m4dbi_unassigned__'
8
8
 
@@ -142,9 +142,15 @@ module M4DBI
142
142
  end
143
143
  if ! pk_hash.empty?
144
144
  rec = self.one_where( pk_hash )
145
+ callbacks[:after_create].each do |block|
146
+ block.yield rec
147
+ end
145
148
  else
146
149
  begin
147
150
  rec = last_record( dbh_ )
151
+ callbacks[:after_create].each do |block|
152
+ block.yield rec
153
+ end
148
154
  rescue NoMethodError => e
149
155
  # ignore
150
156
  #puts "not implemented: #{e.message}"
@@ -221,6 +227,10 @@ module M4DBI
221
227
  stm.execute( *params )
222
228
  end
223
229
 
230
+ def self.after_create(&block)
231
+ callbacks[:after_create] << block
232
+ end
233
+
224
234
  # Example:
225
235
  # M4DBI::Model.one_to_many( Author, Post, :posts, :author, :author_id )
226
236
  # her_posts = some_author.posts
@@ -413,11 +423,14 @@ module M4DBI
413
423
  @models ||= Hash.new
414
424
  @models[ model_key ] ||= Class.new( M4DBI::Model ) do |klass|
415
425
  klass.trait( {
416
- :dbh => h,
417
- :table => table,
418
- :pk => pk_,
419
- :columns => h.table_schema( table.to_sym ).columns,
420
- :st => Hash.new, # prepared statements for all queries
426
+ :dbh => h,
427
+ :table => table,
428
+ :pk => pk_,
429
+ :columns => h.table_schema( table.to_sym ).columns,
430
+ :st => Hash.new, # prepared statements for all queries
431
+ :callbacks => {
432
+ after_create: []
433
+ }
421
434
  } )
422
435
 
423
436
  meta_def( 'pk_str'.to_sym ) do
data/lib/m4dbi/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module M4DBI
2
- VERSION = '0.8.1'
2
+ VERSION = '0.8.2'
3
3
  end
@@ -0,0 +1,84 @@
1
+ require File.join(File.dirname(__FILE__), 'helper')
2
+
3
+ $dbh = connect_to_spec_database
4
+ reset_data
5
+
6
+ describe 'M4DBI::Collection' do
7
+ before do
8
+ @m_author = Class.new( M4DBI::Model( :authors ) )
9
+ @m_post = Class.new( M4DBI::Model( :posts ) )
10
+
11
+ M4DBI::Model.one_to_many(
12
+ @m_author, @m_post, :posts, :author, :author_id
13
+ )
14
+ end
15
+
16
+ it 'accepts additions' do
17
+ num_posts = @m_post.count
18
+
19
+ a = @m_author[ 1 ]
20
+ the_text = 'A new post.'
21
+
22
+ num_posts_of_author = a.posts.count
23
+
24
+ # Insert without auto-incrementing primary key specified
25
+ # Try at least as many times as there were records in the DB,
26
+ # because the sequence used for the IDs is independent of
27
+ # the actual ID values in the DB for some RDBMSes.
28
+ num_posts.times do
29
+ begin
30
+ a.posts << { :text => the_text }
31
+ break # Stop on success
32
+ rescue Exception => e
33
+ if e.message !~ /duplicate/
34
+ raise e
35
+ end
36
+ end
37
+ end
38
+
39
+ a.posts.count.should.equal num_posts_of_author + 1
40
+
41
+ p = a.posts.find { |p| p.text == the_text }
42
+ p.should.not.be.nil
43
+ p.author.should.equal a
44
+
45
+ a_ = @m_author[ 1 ]
46
+ a_.posts.find { |p| p.text == the_text }.should.not.be.nil
47
+
48
+ reset_data
49
+ end
50
+
51
+ it 'facilitates single record deletions' do
52
+ a = @m_author[ 1 ]
53
+ posts = a.posts
54
+ n = posts.size
55
+ p = posts[ 0 ]
56
+
57
+ posts.delete( p ).should.be.true
58
+ a.posts.size.should.equal( n - 1 )
59
+ posts.find { |p_| p_ == p }.should.be.nil
60
+
61
+ reset_data
62
+ end
63
+
64
+ it 'facilitates multi-record deletions' do
65
+ a = @m_author[ 1 ]
66
+ posts = a.posts
67
+ n = posts.size
68
+ posts.delete( :text => 'Third post.' ).should.equal 1
69
+ a.posts.size.should.equal( n - 1 )
70
+ posts.find { |p| p.text == 'Third post.' }.should.be.nil
71
+ posts.find { |p| p.text == 'First post.' }.should.not.be.nil
72
+
73
+ reset_data
74
+ end
75
+
76
+ it 'facilitates table-wide deletion' do
77
+ a = @m_author[ 1 ]
78
+ a.posts.should.not.be.empty
79
+ a.posts.clear.should.be > 0
80
+ a.posts.should.be.empty
81
+
82
+ reset_data
83
+ end
84
+ end
data/spec/model.rb CHANGED
@@ -86,16 +86,16 @@ describe 'A M4DBI::Model subclass' do
86
86
  end
87
87
 
88
88
  it 'provides the database handle it is using' do
89
- begin
90
- @m_author.dbh.should.equal $dbh
89
+ # begin
90
+ # @m_author.dbh.should.equal $dbh
91
91
 
92
- dbh = connect_to_spec_database( ENV[ 'M4DBI_DATABASE2' ] || 'm4dbi2' )
93
- @m_author2 = Class.new( M4DBI::Model( :authors ) )
94
- @m_author2.dbh.should.equal dbh
95
- ensure
96
- # Clean up handles for later specs
97
- connect_to_spec_database
98
- end
92
+ # dbh = connect_to_spec_database( ENV[ 'M4DBI_DATABASE2' ] || 'm4dbi2' )
93
+ # @m_author2 = Class.new( M4DBI::Model( :authors ) )
94
+ # @m_author2.dbh.should.equal dbh
95
+ # ensure
96
+ # # Clean up handles for later specs
97
+ # connect_to_spec_database
98
+ # end
99
99
  end
100
100
 
101
101
  it 'maintains distinction from models of the same name in different databases' do
@@ -670,6 +670,19 @@ describe 'A M4DBI::Model subclass' do
670
670
 
671
671
  reset_data
672
672
  end
673
+
674
+ it 'after creation, executes code provided in an after_create hook' do
675
+ class Author < M4DBI::Model( :authors )
676
+ after_create do |author|
677
+ $test = 2
678
+ author.name = 'different name'
679
+ end
680
+ end
681
+ $test.should.not.equal 2
682
+ a = Author.create(name: 'theauthor')
683
+ $test.should.equal 2
684
+ a.name.should.equal 'different name'
685
+ end
673
686
  end
674
687
 
675
688
  describe 'A created M4DBI::Model subclass instance' do
@@ -950,7 +963,6 @@ describe 'A found M4DBI::Model subclass instance' do
950
963
  p.save!
951
964
  end
952
965
  end
953
-
954
966
  end
955
967
 
956
968
  describe 'M4DBI::Model (relationships)' do
@@ -1029,83 +1041,3 @@ describe 'M4DBI::Model (relationships)' do
1029
1041
  @m_fan[ 5 ].authors_liked.should.be.empty
1030
1042
  end
1031
1043
  end
1032
-
1033
- describe 'M4DBI::Collection' do
1034
- before do
1035
- @m_author = Class.new( M4DBI::Model( :authors ) )
1036
- @m_post = Class.new( M4DBI::Model( :posts ) )
1037
-
1038
- M4DBI::Model.one_to_many(
1039
- @m_author, @m_post, :posts, :author, :author_id
1040
- )
1041
- end
1042
-
1043
- it 'accepts additions' do
1044
- num_posts = @m_post.count
1045
-
1046
- a = @m_author[ 1 ]
1047
- the_text = 'A new post.'
1048
-
1049
- num_posts_of_author = a.posts.count
1050
-
1051
- # Insert without auto-incrementing primary key specified
1052
- # Try at least as many times as there were records in the DB,
1053
- # because the sequence used for the IDs is independent of
1054
- # the actual ID values in the DB for some RDBMSes.
1055
- num_posts.times do
1056
- begin
1057
- a.posts << { :text => the_text }
1058
- break # Stop on success
1059
- rescue Exception => e
1060
- if e.message !~ /duplicate/
1061
- raise e
1062
- end
1063
- end
1064
- end
1065
-
1066
- a.posts.count.should.equal num_posts_of_author + 1
1067
-
1068
- p = a.posts.find { |p| p.text == the_text }
1069
- p.should.not.be.nil
1070
- p.author.should.equal a
1071
-
1072
- a_ = @m_author[ 1 ]
1073
- a_.posts.find { |p| p.text == the_text }.should.not.be.nil
1074
-
1075
- reset_data
1076
- end
1077
-
1078
- it 'facilitates single record deletions' do
1079
- a = @m_author[ 1 ]
1080
- posts = a.posts
1081
- n = posts.size
1082
- p = posts[ 0 ]
1083
-
1084
- posts.delete( p ).should.be.true
1085
- a.posts.size.should.equal( n - 1 )
1086
- posts.find { |p_| p_ == p }.should.be.nil
1087
-
1088
- reset_data
1089
- end
1090
-
1091
- it 'facilitates multi-record deletions' do
1092
- a = @m_author[ 1 ]
1093
- posts = a.posts
1094
- n = posts.size
1095
- posts.delete( :text => 'Third post.' ).should.equal 1
1096
- a.posts.size.should.equal( n - 1 )
1097
- posts.find { |p| p.text == 'Third post.' }.should.be.nil
1098
- posts.find { |p| p.text == 'First post.' }.should.not.be.nil
1099
-
1100
- reset_data
1101
- end
1102
-
1103
- it 'facilitates table-wide deletion' do
1104
- a = @m_author[ 1 ]
1105
- a.posts.should.not.be.empty
1106
- a.posts.clear.should.be > 0
1107
- a.posts.should.be.empty
1108
-
1109
- reset_data
1110
- end
1111
- end
metadata CHANGED
@@ -1,58 +1,61 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: m4dbi
3
- version: !ruby/object:Gem::Version
4
- version: 0.8.1
3
+ version: !ruby/object:Gem::Version
4
+ hash: 59
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 8
9
+ - 2
10
+ version: 0.8.2
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Pistos
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2012-03-21 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2012-06-25 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: metaid
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
30
- - !ruby/object:Gem::Dependency
31
- name: rdbi
32
- requirement: !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
33
24
  none: false
34
- requirements:
35
- - - ! '>='
36
- - !ruby/object:Gem::Version
37
- version: '0'
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
38
32
  type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rdbi
39
36
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
37
+ requirement: &id002 !ruby/object:Gem::Requirement
41
38
  none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
46
- description: M4DBI provides models, associations and some convenient extensions to
47
- RDBI.
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :runtime
47
+ version_requirements: *id002
48
+ description: M4DBI provides models, associations and some convenient extensions to RDBI.
48
49
  email: m4dbi dot pistos at purepistos dot net
49
50
  executables: []
51
+
50
52
  extensions: []
51
- extra_rdoc_files:
53
+
54
+ extra_rdoc_files:
52
55
  - README.rdoc
53
56
  - CHANGELOG
54
57
  - LICENCE
55
- files:
58
+ files:
56
59
  - README.rdoc
57
60
  - CHANGELOG
58
61
  - LICENCE
@@ -69,34 +72,44 @@ files:
69
72
  - spec/database.rb
70
73
  - spec/model.rb
71
74
  - spec/helper.rb
75
+ - spec/collection.rb
72
76
  - spec/hash.rb
73
77
  homepage: https://github.com/Pistos/m4dbi
74
78
  licenses: []
79
+
75
80
  post_install_message:
76
81
  rdoc_options: []
77
- require_paths:
82
+
83
+ require_paths:
78
84
  - lib
79
- required_ruby_version: !ruby/object:Gem::Requirement
85
+ required_ruby_version: !ruby/object:Gem::Requirement
80
86
  none: false
81
- requirements:
82
- - - ! '>='
83
- - !ruby/object:Gem::Version
84
- version: '0'
85
- required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ hash: 3
91
+ segments:
92
+ - 0
93
+ version: "0"
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
95
  none: false
87
- requirements:
88
- - - ! '>='
89
- - !ruby/object:Gem::Version
90
- version: '0'
91
- requirements:
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ requirements:
92
104
  - bacon (optional)
93
105
  rubyforge_project:
94
- rubygems_version: 1.8.18
106
+ rubygems_version: 1.8.24
95
107
  signing_key:
96
108
  specification_version: 3
97
109
  summary: Models (and More) for RDBI
98
- test_files:
110
+ test_files:
99
111
  - spec/database.rb
100
112
  - spec/model.rb
101
113
  - spec/helper.rb
114
+ - spec/collection.rb
102
115
  - spec/hash.rb