m4dbi 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/m4dbi.rb +1 -1
- data/lib/m4dbi/hash.rb +9 -7
- data/lib/m4dbi/model.rb +55 -55
- data/spec/model.rb +159 -139
- metadata +3 -3
data/lib/m4dbi.rb
CHANGED
data/lib/m4dbi/hash.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
class Hash
|
2
2
|
COMPACT_NILS = true
|
3
3
|
DONT_COMPACT_NILS = false
|
4
|
-
|
4
|
+
|
5
5
|
# Takes an optional block to provide a single "field = ?" type subclause
|
6
6
|
# for each key-value pair.
|
7
7
|
def to_clause( join_string, compact_nils = DONT_COMPACT_NILS )
|
@@ -21,7 +21,7 @@ class Hash
|
|
21
21
|
end
|
22
22
|
[ clause, values_ ]
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
def to_where_clause
|
26
26
|
to_clause( " AND ", COMPACT_NILS ) { |field|
|
27
27
|
if self[ field ].nil?
|
@@ -31,19 +31,21 @@ class Hash
|
|
31
31
|
end
|
32
32
|
}
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
def to_set_clause
|
36
36
|
to_clause( ", " )
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
if method_defined? :slice
|
40
40
|
warn "Hash#slice already defined; redefining."
|
41
41
|
end
|
42
42
|
def slice( *desired_keys )
|
43
43
|
Hash[
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
*(
|
45
|
+
select { |key,value|
|
46
|
+
desired_keys.include? key
|
47
|
+
}.flatten
|
48
|
+
)
|
47
49
|
]
|
48
50
|
end
|
49
51
|
end
|
data/lib/m4dbi/model.rb
CHANGED
@@ -6,11 +6,11 @@ module DBI
|
|
6
6
|
#attr_reader :row
|
7
7
|
ancestral_trait_reader :dbh, :table
|
8
8
|
ancestral_trait_class_reader :dbh, :table, :pk, :columns
|
9
|
-
|
9
|
+
|
10
10
|
M4DBI_UNASSIGNED = '__m4dbi_unassigned__'
|
11
|
-
|
11
|
+
|
12
12
|
extend Enumerable
|
13
|
-
|
13
|
+
|
14
14
|
def self.[]( first_arg, *args )
|
15
15
|
if args.size == 0
|
16
16
|
case first_arg
|
@@ -27,27 +27,27 @@ module DBI
|
|
27
27
|
clause = pk_clause
|
28
28
|
values = [ first_arg ] + args
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
row = dbh.select_one(
|
32
32
|
"SELECT * FROM #{table} WHERE #{clause}",
|
33
33
|
*values
|
34
34
|
)
|
35
|
-
|
35
|
+
|
36
36
|
if row
|
37
37
|
self.new( row )
|
38
38
|
end
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
def self.pk_clause
|
42
42
|
pk.map { |col|
|
43
43
|
"#{col} = ?"
|
44
44
|
}.join( ' AND ' )
|
45
45
|
end
|
46
|
-
|
46
|
+
|
47
47
|
def self.from_rows( rows )
|
48
48
|
rows.map { |r| self.new( r ) }
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
def self.where( conditions, *args )
|
52
52
|
case conditions
|
53
53
|
when String
|
@@ -57,12 +57,12 @@ module DBI
|
|
57
57
|
cond, params = conditions.to_where_clause
|
58
58
|
sql = "SELECT * FROM #{table} WHERE #{cond}"
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
self.from_rows(
|
62
62
|
dbh.select_all( sql, *params )
|
63
63
|
)
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
def self.one_where( conditions, *args )
|
67
67
|
case conditions
|
68
68
|
when String
|
@@ -72,35 +72,35 @@ module DBI
|
|
72
72
|
cond, params = conditions.to_where_clause
|
73
73
|
sql = "SELECT * FROM #{table} WHERE #{cond} LIMIT 1"
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
row = dbh.select_one( sql, *params )
|
77
77
|
if row
|
78
78
|
self.new( row )
|
79
79
|
end
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
def self.all
|
83
83
|
self.from_rows(
|
84
84
|
dbh.select_all( "SELECT * FROM #{table}" )
|
85
85
|
)
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
# TODO: Perhaps we'll use cursors for Model#each.
|
89
89
|
def self.each( &block )
|
90
90
|
self.all.each( &block )
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
def self.one
|
94
94
|
row = dbh.select_one( "SELECT * FROM #{table} LIMIT 1" )
|
95
95
|
if row
|
96
96
|
self.new( row )
|
97
97
|
end
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
def self.count
|
101
101
|
dbh.select_column( "SELECT COUNT(*) FROM #{table}" ).to_i
|
102
102
|
end
|
103
|
-
|
103
|
+
|
104
104
|
def self.create( hash = {} )
|
105
105
|
if block_given?
|
106
106
|
row = DBI::Row.new(
|
@@ -115,13 +115,13 @@ module DBI
|
|
115
115
|
end
|
116
116
|
end
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
keys = hash.keys
|
120
120
|
cols = keys.join( ',' )
|
121
121
|
values = keys.map { |key| hash[ key ] }
|
122
122
|
value_placeholders = values.map { |v| '?' }.join( ',' )
|
123
123
|
rec = nil
|
124
|
-
|
124
|
+
|
125
125
|
dbh.one_transaction do |dbh_|
|
126
126
|
num_inserted = dbh_.do(
|
127
127
|
"INSERT INTO #{table} ( #{cols} ) VALUES ( #{value_placeholders} )",
|
@@ -148,10 +148,10 @@ module DBI
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
end
|
151
|
-
|
151
|
+
|
152
152
|
rec
|
153
153
|
end
|
154
|
-
|
154
|
+
|
155
155
|
def self.find_or_create( hash = nil )
|
156
156
|
item = nil
|
157
157
|
error = nil
|
@@ -170,37 +170,37 @@ module DBI
|
|
170
170
|
raise error
|
171
171
|
end
|
172
172
|
end
|
173
|
-
|
173
|
+
|
174
174
|
def self.select_all( *args )
|
175
175
|
self.from_rows(
|
176
176
|
dbh.select_all( *args )
|
177
177
|
)
|
178
178
|
end
|
179
|
-
|
179
|
+
|
180
180
|
def self.select_one( *args )
|
181
181
|
row = dbh.select_one( *args )
|
182
182
|
if row
|
183
183
|
self.new( row )
|
184
184
|
end
|
185
185
|
end
|
186
|
-
|
186
|
+
|
187
187
|
class << self
|
188
188
|
alias s select_all
|
189
189
|
alias s1 select_one
|
190
190
|
end
|
191
|
-
|
191
|
+
|
192
192
|
def self.update( where_hash_or_clause, set_hash )
|
193
193
|
where_clause = nil
|
194
194
|
set_clause = nil
|
195
195
|
where_params = nil
|
196
|
-
|
196
|
+
|
197
197
|
if where_hash_or_clause.respond_to? :keys
|
198
198
|
where_clause, where_params = where_hash_or_clause.to_where_clause
|
199
199
|
else
|
200
200
|
where_clause = where_hash_or_clause
|
201
201
|
where_params = []
|
202
202
|
end
|
203
|
-
|
203
|
+
|
204
204
|
set_clause, set_params = set_hash.to_set_clause
|
205
205
|
params = set_params + where_params
|
206
206
|
dbh.do(
|
@@ -208,7 +208,7 @@ module DBI
|
|
208
208
|
*params
|
209
209
|
)
|
210
210
|
end
|
211
|
-
|
211
|
+
|
212
212
|
def self.update_one( *args )
|
213
213
|
set_clause, set_params = args[ -1 ].to_set_clause
|
214
214
|
pk_values = args[ 0..-2 ]
|
@@ -218,9 +218,9 @@ module DBI
|
|
218
218
|
*params
|
219
219
|
)
|
220
220
|
end
|
221
|
-
|
221
|
+
|
222
222
|
# Example:
|
223
|
-
# DBI::Model.one_to_many( Author, :posts,
|
223
|
+
# DBI::Model.one_to_many( Author, Post, :posts, :author, :author_id )
|
224
224
|
# her_posts = some_author.posts
|
225
225
|
# the_author = some_post.author
|
226
226
|
def self.one_to_many( the_one, the_many, many_as, one_as, the_one_fk )
|
@@ -234,7 +234,7 @@ module DBI
|
|
234
234
|
send( "#{the_one_fk}=".to_sym, new_one.pk )
|
235
235
|
end
|
236
236
|
end
|
237
|
-
|
237
|
+
|
238
238
|
# Example:
|
239
239
|
# DBI::Model.many_to_many(
|
240
240
|
# @m_author, @m_fan, :authors_liked, :fans, :authors_fans, :author_id, :fan_id
|
@@ -258,7 +258,7 @@ module DBI
|
|
258
258
|
pk
|
259
259
|
)
|
260
260
|
end
|
261
|
-
|
261
|
+
|
262
262
|
model2.class_def( m1_as.to_sym ) do
|
263
263
|
model1.select_all(
|
264
264
|
%{
|
@@ -276,9 +276,9 @@ module DBI
|
|
276
276
|
)
|
277
277
|
end
|
278
278
|
end
|
279
|
-
|
279
|
+
|
280
280
|
# ------------------- :nodoc:
|
281
|
-
|
281
|
+
|
282
282
|
def initialize( row )
|
283
283
|
if not row.respond_to?( "[]".to_sym ) or not row.respond_to?( "[]=".to_sym )
|
284
284
|
raise DBI::Error.new( "Attempted to instantiate DBI::Model with an invalid argument (#{row.inspect}). (Expecting DBI::Row.)" )
|
@@ -288,7 +288,7 @@ module DBI
|
|
288
288
|
end
|
289
289
|
@row = row
|
290
290
|
end
|
291
|
-
|
291
|
+
|
292
292
|
def method_missing( method, *args )
|
293
293
|
begin
|
294
294
|
@row.send( method, *args )
|
@@ -300,7 +300,7 @@ module DBI
|
|
300
300
|
)
|
301
301
|
end
|
302
302
|
end
|
303
|
-
|
303
|
+
|
304
304
|
# Returns a single value for single-column primary keys,
|
305
305
|
# returns an Array for multi-column primary keys.
|
306
306
|
def pk
|
@@ -310,36 +310,36 @@ module DBI
|
|
310
310
|
pk_values
|
311
311
|
end
|
312
312
|
end
|
313
|
-
|
313
|
+
|
314
314
|
# Always returns an Array of values, even for single-column primary keys.
|
315
315
|
def pk_values
|
316
316
|
pk_columns.map { |col|
|
317
317
|
@row[ col ]
|
318
318
|
}
|
319
319
|
end
|
320
|
-
|
320
|
+
|
321
321
|
def pk_columns
|
322
322
|
self.class.pk
|
323
323
|
end
|
324
|
-
|
324
|
+
|
325
325
|
def pk_clause
|
326
326
|
pk_columns.map { |col|
|
327
327
|
"#{col} = ?"
|
328
328
|
}.join( ' AND ' )
|
329
329
|
end
|
330
|
-
|
330
|
+
|
331
331
|
def ==( other )
|
332
332
|
other and ( pk == other.pk )
|
333
333
|
end
|
334
|
-
|
334
|
+
|
335
335
|
def hash
|
336
336
|
"#{self.class.hash}#{pk}".to_i
|
337
337
|
end
|
338
|
-
|
338
|
+
|
339
339
|
def eql?( other )
|
340
340
|
hash == other.hash
|
341
341
|
end
|
342
|
-
|
342
|
+
|
343
343
|
def set( hash )
|
344
344
|
set_clause, set_params = hash.to_set_clause
|
345
345
|
set_params << pk
|
@@ -354,7 +354,7 @@ module DBI
|
|
354
354
|
end
|
355
355
|
num_updated
|
356
356
|
end
|
357
|
-
|
357
|
+
|
358
358
|
# Returns true iff the record and only the record was successfully deleted.
|
359
359
|
def delete
|
360
360
|
num_deleted = dbh.do(
|
@@ -363,13 +363,13 @@ module DBI
|
|
363
363
|
)
|
364
364
|
num_deleted == 1
|
365
365
|
end
|
366
|
-
|
366
|
+
|
367
367
|
# save does nothing. It exists to provide compatibility with other ORMs.
|
368
368
|
def save
|
369
369
|
nil
|
370
370
|
end
|
371
371
|
end
|
372
|
-
|
372
|
+
|
373
373
|
# Define a new DBI::Model like this:
|
374
374
|
# class Post < DBI::Model( :posts ); end
|
375
375
|
# You can specify the primary key column(s) using an array, like so:
|
@@ -382,7 +382,7 @@ module DBI
|
|
382
382
|
if not pk_.respond_to? :each
|
383
383
|
raise DBI::Error.new( "Primary key must be enumerable (was given #{pk_.inspect})" )
|
384
384
|
end
|
385
|
-
|
385
|
+
|
386
386
|
model_key =
|
387
387
|
# DBD-dependent. Not all DBDs have dbname implemented by M4DBI.
|
388
388
|
if h.respond_to? :dbname
|
@@ -390,7 +390,7 @@ module DBI
|
|
390
390
|
else
|
391
391
|
table
|
392
392
|
end
|
393
|
-
|
393
|
+
|
394
394
|
@models ||= Hash.new
|
395
395
|
@models[ model_key ] ||= Class.new( DBI::Model ) do |klass|
|
396
396
|
klass.trait( {
|
@@ -399,31 +399,31 @@ module DBI
|
|
399
399
|
:pk => pk_,
|
400
400
|
:columns => h.columns( table.to_s ),
|
401
401
|
} )
|
402
|
-
|
402
|
+
|
403
403
|
if defined?( DBI::DBD::Pg::Database ) and DBI::DBD::Pg::Database === h.handle
|
404
404
|
# TODO: This is broken for non-SERIAL or multi-column primary keys
|
405
405
|
meta_def( "last_record".to_sym ) do |dbh_|
|
406
|
-
self.s1 "SELECT * FROM #{table} WHERE #{pk} = currval( '#{table}_#{pk}_seq' );"
|
406
|
+
self.s1 "SELECT * FROM #{table} WHERE #{pk} = currval( '#{table}_#{pk}_seq' );"
|
407
407
|
end
|
408
408
|
elsif defined?( DBI::DBD::Mysql::Database ) and DBI::DBD::Mysql::Database === h.handle
|
409
409
|
meta_def( "last_record".to_sym ) do |dbh_|
|
410
|
-
self.s1 "SELECT * FROM #{table} WHERE #{pk} = LAST_INSERT_ID();"
|
410
|
+
self.s1 "SELECT * FROM #{table} WHERE #{pk} = LAST_INSERT_ID();"
|
411
411
|
end
|
412
412
|
elsif defined?( DBI::DBD::SQLite3::Database ) and DBI::DBD::SQLite3::Database === h.handle
|
413
413
|
meta_def( "last_record".to_sym ) do |dbh_|
|
414
|
-
self.s1 "SELECT * FROM #{table} WHERE #{pk} = last_insert_rowid();"
|
414
|
+
self.s1 "SELECT * FROM #{table} WHERE #{pk} = last_insert_rowid();"
|
415
415
|
end
|
416
416
|
# TODO: more DBDs
|
417
417
|
end
|
418
|
-
|
418
|
+
|
419
419
|
klass.trait[ :columns ].each do |col|
|
420
420
|
colname = col[ 'name' ]
|
421
|
-
|
421
|
+
|
422
422
|
# Column readers
|
423
423
|
class_def( colname.to_sym ) do
|
424
424
|
@row[ colname ]
|
425
425
|
end
|
426
|
-
|
426
|
+
|
427
427
|
# Column writers
|
428
428
|
class_def( "#{colname}=".to_sym ) do |new_value|
|
429
429
|
num_changed = dbh.do(
|
@@ -438,5 +438,5 @@ module DBI
|
|
438
438
|
end
|
439
439
|
end
|
440
440
|
end
|
441
|
-
|
441
|
+
|
442
442
|
end
|
data/spec/model.rb
CHANGED
@@ -19,7 +19,7 @@ class ManyCol < DBI::Model( :many_col_table )
|
|
19
19
|
def inc
|
20
20
|
self.c1 = c1 + 10
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def dec
|
24
24
|
self.c1 = c1 - 10
|
25
25
|
end
|
@@ -34,22 +34,23 @@ describe 'A DBI::Model subclass' do
|
|
34
34
|
@m_post = Class.new( DBI::Model( :posts ) )
|
35
35
|
@m_empty = Class.new( DBI::Model( :empty_table ) )
|
36
36
|
@m_mc = Class.new( DBI::Model( :many_col_table ) )
|
37
|
+
@m_nipk = Class.new( DBI::Model( :non_id_pk, [ :str ] ) )
|
37
38
|
@m_mcpk = Class.new( DBI::Model( :mcpk, [ :kc1, :kc2 ] ) )
|
38
39
|
class Author < DBI::Model( :authors ); end
|
39
40
|
end
|
40
|
-
|
41
|
+
|
41
42
|
it 'can be defined' do
|
42
43
|
@m_author.should.not.be.nil
|
43
44
|
@m_post.should.not.be.nil
|
44
45
|
end
|
45
|
-
|
46
|
+
|
46
47
|
it 'maintains identity across different inheritances' do
|
47
48
|
should.not.raise do
|
48
49
|
class Author < DBI::Model( :authors ); end
|
49
50
|
class Author < DBI::Model( :authors ); end
|
50
51
|
end
|
51
52
|
end
|
52
|
-
|
53
|
+
|
53
54
|
it 'maintains member methods across redefinitions' do
|
54
55
|
class Author < DBI::Model( :authors )
|
55
56
|
def method1; 1; end
|
@@ -61,40 +62,40 @@ describe 'A DBI::Model subclass' do
|
|
61
62
|
a.method1.should.equal 1
|
62
63
|
a.method2.should.equal 2
|
63
64
|
end
|
64
|
-
|
65
|
+
|
65
66
|
it 'maintains identity across different database handles of the same database' do
|
66
67
|
# If you try to subclass a class a second time with a different parent class,
|
67
68
|
# Ruby raises an exception.
|
68
69
|
should.not.raise do
|
69
70
|
original_handle = DBI::DatabaseHandle.last_handle
|
70
|
-
|
71
|
+
|
71
72
|
class Author < DBI::Model( :authors ); end
|
72
|
-
|
73
|
+
|
73
74
|
dbh = connect_to_spec_database
|
74
75
|
new_handle = DBI::DatabaseHandle.last_handle
|
75
76
|
new_handle.should.equal dbh
|
76
77
|
new_handle.should.not.equal original_handle
|
77
|
-
|
78
|
+
|
78
79
|
class Author < DBI::Model( :authors ); end
|
79
80
|
end
|
80
81
|
end
|
81
|
-
|
82
|
+
|
82
83
|
it 'maintains distinction from models of the same name in different databases' do
|
83
84
|
begin
|
84
85
|
a1 = @m_author[ 1 ]
|
85
86
|
a1.should.not.be.nil
|
86
87
|
a1.name.should.equal 'author1'
|
87
|
-
|
88
|
-
dbh = connect_to_spec_database( 'm4dbi2' )
|
88
|
+
|
89
|
+
dbh = connect_to_spec_database( ENV[ 'M4DBI_DATABASE2' ] || 'm4dbi2' )
|
89
90
|
reset_data( dbh, "test-data2.sql" )
|
90
|
-
|
91
|
+
|
91
92
|
@m_author2 = Class.new( DBI::Model( :authors ) )
|
92
|
-
|
93
|
+
|
93
94
|
@m_author2[ 1 ].should.be.nil
|
94
95
|
a11 = @m_author2[ 11 ]
|
95
96
|
a11.should.not.be.nil
|
96
97
|
a11.name.should.equal 'author11'
|
97
|
-
|
98
|
+
|
98
99
|
a2 = @m_author[ 2 ]
|
99
100
|
a2.should.not.be.nil
|
100
101
|
a2.name.should.equal 'author2'
|
@@ -104,7 +105,7 @@ describe 'A DBI::Model subclass' do
|
|
104
105
|
connect_to_spec_database
|
105
106
|
end
|
106
107
|
end
|
107
|
-
|
108
|
+
|
108
109
|
it 'raises an exception when creating with invalid arguments' do
|
109
110
|
should.raise( DBI::Error ) do
|
110
111
|
@m_author.new nil
|
@@ -116,82 +117,94 @@ describe 'A DBI::Model subclass' do
|
|
116
117
|
@m_author.new Object.new
|
117
118
|
end
|
118
119
|
end
|
119
|
-
|
120
|
+
|
120
121
|
it 'provides hash-like single-record access via #[ primary_key_value ]' do
|
121
122
|
o = @m_author[ 1 ]
|
122
123
|
o.should.not.be.nil
|
123
124
|
o.class.should.equal @m_author
|
124
125
|
o.name.should.equal 'author1'
|
125
|
-
|
126
|
+
|
126
127
|
o = @m_author[ 2 ]
|
127
128
|
o.should.not.be.nil
|
128
129
|
o.class.should.equal @m_author
|
129
130
|
o.name.should.equal 'author2'
|
130
|
-
|
131
|
+
|
132
|
+
o = @m_nipk[ 'one' ]
|
133
|
+
o.should.not.be.nil
|
134
|
+
o.class.should.equal @m_nipk
|
135
|
+
o.c1.should.equal 1
|
136
|
+
o.c2.should.equal 2
|
137
|
+
|
138
|
+
o = @m_nipk[ 'two' ]
|
139
|
+
o.should.not.be.nil
|
140
|
+
o.class.should.equal @m_nipk
|
141
|
+
o.c1.should.equal 2
|
142
|
+
o.c2.should.equal 4
|
143
|
+
|
131
144
|
o = @m_mcpk[ [ 2, 2 ] ]
|
132
145
|
o.should.not.be.nil
|
133
146
|
o.class.should.equal @m_mcpk
|
134
147
|
o.val.should.equal 'two two'
|
135
|
-
|
148
|
+
|
136
149
|
o = @m_mcpk[ 1, 1 ]
|
137
150
|
o.should.not.be.nil
|
138
151
|
o.class.should.equal @m_mcpk
|
139
152
|
o.val.should.equal 'one one'
|
140
|
-
|
153
|
+
|
141
154
|
o = @m_mcpk[ { :kc1 => 5, :kc2 => 6 } ]
|
142
155
|
o.should.not.be.nil
|
143
156
|
o.class.should.equal @m_mcpk
|
144
157
|
o.val.should.equal 'five six'
|
145
|
-
|
158
|
+
|
146
159
|
should.not.raise( DBI::Error ) do
|
147
160
|
o = @m_author[ nil ]
|
148
161
|
o.should.be.nil
|
149
162
|
end
|
150
163
|
end
|
151
|
-
|
164
|
+
|
152
165
|
it 'provides hash-like single-record access via #[ field_hash ]' do
|
153
166
|
o = @m_author[ :name => 'author1' ]
|
154
167
|
o.should.not.be.nil
|
155
168
|
o.class.should.equal @m_author
|
156
169
|
o.id.should.equal 1
|
157
|
-
|
170
|
+
|
158
171
|
o = @m_post[ :author_id => 1 ]
|
159
172
|
o.should.not.be.nil
|
160
173
|
o.class.should.equal @m_post
|
161
174
|
o.text.should.equal 'First post.'
|
162
|
-
|
175
|
+
|
163
176
|
o = @m_mc[ :c1 => 100, :c2 => 50 ]
|
164
177
|
o.should.not.be.nil
|
165
178
|
o.class.should.equal @m_mc
|
166
179
|
o.c3.should.equal 20
|
167
|
-
|
180
|
+
|
168
181
|
o = @m_mc[ :c1 => 100, :c2 => nil ]
|
169
182
|
o.should.not.be.nil
|
170
183
|
o.class.should.equal @m_mc
|
171
184
|
o.c3.should.equal 40
|
172
185
|
end
|
173
|
-
|
186
|
+
|
174
187
|
it 'returns nil from #[] when no record is found' do
|
175
188
|
o = @m_author[ 999 ]
|
176
189
|
o.should.be.nil
|
177
|
-
|
190
|
+
|
178
191
|
o = @m_author[ :name => 'foobar' ]
|
179
192
|
o.should.be.nil
|
180
193
|
end
|
181
|
-
|
194
|
+
|
182
195
|
it 'provides multi-record access via #where( Hash )' do
|
183
196
|
posts = @m_post.where( :author_id => 1 )
|
184
197
|
posts.should.not.be.nil
|
185
198
|
posts.should.not.be.empty
|
186
199
|
posts.size.should.equal 2
|
187
200
|
posts[ 0 ].class.should.equal @m_post
|
188
|
-
|
201
|
+
|
189
202
|
sorted_posts = posts.sort { |p1,p2|
|
190
203
|
p1._id <=> p2._id
|
191
204
|
}
|
192
205
|
p = sorted_posts.first
|
193
206
|
p.text.should.equal 'First post.'
|
194
|
-
|
207
|
+
|
195
208
|
rows = @m_mc.where( :c1 => 100, :c2 => 50 )
|
196
209
|
rows.should.not.be.nil
|
197
210
|
rows.should.not.be.empty
|
@@ -200,7 +213,7 @@ describe 'A DBI::Model subclass' do
|
|
200
213
|
row.class.should.equal @m_mc
|
201
214
|
row.c1.should.equal 100
|
202
215
|
row.c3.should.equal 20
|
203
|
-
|
216
|
+
|
204
217
|
rows = @m_mc.where( :c1 => 100, :c2 => nil )
|
205
218
|
rows.should.not.be.nil
|
206
219
|
rows.should.not.be.empty
|
@@ -209,85 +222,85 @@ describe 'A DBI::Model subclass' do
|
|
209
222
|
row.class.should.equal @m_mc
|
210
223
|
row.c1.should.equal 100
|
211
224
|
row.c3.should.equal 40
|
212
|
-
end
|
213
|
-
|
225
|
+
end
|
226
|
+
|
214
227
|
it 'provides multi-record access via #where( String )' do
|
215
228
|
posts = @m_post.where( "id < 3" )
|
216
229
|
posts.should.not.be.nil
|
217
230
|
posts.should.not.be.empty
|
218
231
|
posts.size.should.equal 2
|
219
232
|
posts[ 0 ].class.should.equal @m_post
|
220
|
-
|
233
|
+
|
221
234
|
sorted_posts = posts.sort { |p1,p2|
|
222
235
|
p2._id <=> p1._id
|
223
236
|
}
|
224
237
|
p = sorted_posts.first
|
225
238
|
p.text.should.equal 'Second post.'
|
226
239
|
end
|
227
|
-
|
240
|
+
|
228
241
|
it 'provides multi-record access via #where( String, param, param... )' do
|
229
242
|
posts = @m_post.where( "id < ?", 3 )
|
230
243
|
posts.should.not.be.nil
|
231
244
|
posts.should.not.be.empty
|
232
245
|
posts.size.should.equal 2
|
233
246
|
posts[ 0 ].class.should.equal @m_post
|
234
|
-
|
247
|
+
|
235
248
|
sorted_posts = posts.sort { |p1,p2|
|
236
249
|
p2._id <=> p1._id
|
237
250
|
}
|
238
251
|
p = sorted_posts.first
|
239
252
|
p.text.should.equal 'Second post.'
|
240
253
|
end
|
241
|
-
|
254
|
+
|
242
255
|
it 'returns an empty array from #where when no records are found' do
|
243
256
|
a = @m_author.where( :id => 999 )
|
244
257
|
a.should.be.empty
|
245
|
-
|
258
|
+
|
246
259
|
p = @m_post.where( "text = 'aoeu'" )
|
247
260
|
p.should.be.empty
|
248
261
|
end
|
249
|
-
|
262
|
+
|
250
263
|
it 'provides single-record access via #one_where( Hash )' do
|
251
264
|
post = @m_post.one_where( :author_id => 2 )
|
252
265
|
post.should.not.be.nil
|
253
266
|
post.class.should.equal @m_post
|
254
267
|
post.text.should.equal 'Second post.'
|
255
|
-
|
268
|
+
|
256
269
|
row = @m_mc.one_where( :c1 => 100, :c2 => nil )
|
257
270
|
row.should.not.be.nil
|
258
271
|
row.class.should.equal @m_mc
|
259
272
|
row.c1.should.equal 100
|
260
273
|
row.c3.should.equal 40
|
261
274
|
end
|
262
|
-
|
275
|
+
|
263
276
|
it 'provides single-record access via #one_where( String )' do
|
264
277
|
post = @m_post.one_where( "text LIKE '%Third%'" )
|
265
278
|
post.should.not.be.nil
|
266
279
|
post.class.should.equal @m_post
|
267
280
|
post.id.should.equal 3
|
268
281
|
end
|
269
|
-
|
282
|
+
|
270
283
|
it 'provides single-record access via #one_where( String, param, param... )' do
|
271
284
|
post = @m_post.one_where( "text LIKE ?", '%Third%' )
|
272
285
|
post.should.not.be.nil
|
273
286
|
post.class.should.equal @m_post
|
274
287
|
post.id.should.equal 3
|
275
288
|
end
|
276
|
-
|
289
|
+
|
277
290
|
it 'returns nil from #one_where when no record is found' do
|
278
291
|
a = @m_author.one_where( :id => 999 )
|
279
292
|
a.should.be.nil
|
280
|
-
|
293
|
+
|
281
294
|
p = @m_post.one_where( "text = 'aoeu'" )
|
282
295
|
p.should.be.nil
|
283
296
|
end
|
284
|
-
|
297
|
+
|
285
298
|
it 'returns all table records via #all' do
|
286
299
|
rows = @m_author.all
|
287
300
|
rows.should.not.be.nil
|
288
301
|
rows.should.not.be.empty
|
289
302
|
rows.size.should.equal 3
|
290
|
-
|
303
|
+
|
291
304
|
rows[ 0 ].id.should.equal 1
|
292
305
|
rows[ 0 ].class.should.equal @m_author
|
293
306
|
rows[ 0 ].name.should.equal 'author1'
|
@@ -295,29 +308,29 @@ describe 'A DBI::Model subclass' do
|
|
295
308
|
rows[ 1 ].class.should.equal @m_author
|
296
309
|
rows[ 1 ].name.should.equal 'author2'
|
297
310
|
end
|
298
|
-
|
311
|
+
|
299
312
|
it 'returns an empty array when #all is called on an empty table' do
|
300
313
|
rows = @m_empty.all
|
301
314
|
rows.should.not.be.nil
|
302
315
|
rows.should.be.empty
|
303
316
|
end
|
304
|
-
|
317
|
+
|
305
318
|
it 'returns a random single record from #one' do
|
306
319
|
one = @m_author.one
|
307
320
|
one.should.not.be.nil
|
308
321
|
one.class.should.equal @m_author
|
309
322
|
end
|
310
|
-
|
323
|
+
|
311
324
|
it 'returns nil from #one on an empty table' do
|
312
325
|
one = @m_empty.one
|
313
326
|
one.should.be.nil
|
314
327
|
end
|
315
|
-
|
328
|
+
|
316
329
|
it 'returns the record count via #count' do
|
317
330
|
n = @m_author.count
|
318
331
|
n.should.equal 3
|
319
332
|
end
|
320
|
-
|
333
|
+
|
321
334
|
it 'provides a means to create new records via #create( Hash )' do
|
322
335
|
a = @m_author.create(
|
323
336
|
:id => 9,
|
@@ -329,22 +342,22 @@ describe 'A DBI::Model subclass' do
|
|
329
342
|
a.should.respond_to :name
|
330
343
|
a.should.not.respond_to :no_column_by_this_name
|
331
344
|
a.name.should.equal 'author9'
|
332
|
-
|
345
|
+
|
333
346
|
a_ = @m_author[ 9 ]
|
334
347
|
a_.should.not.be.nil
|
335
348
|
a_.should.equal a
|
336
349
|
a_.name.should.equal 'author9'
|
337
|
-
|
350
|
+
|
338
351
|
reset_data
|
339
352
|
end
|
340
|
-
|
353
|
+
|
341
354
|
it 'provides a means to create new records via #create { |r| }' do
|
342
355
|
should.raise( NoMethodError ) do
|
343
356
|
@m_author.create { |rec|
|
344
357
|
rec.no_such_column = 'foobar'
|
345
358
|
}
|
346
359
|
end
|
347
|
-
|
360
|
+
|
348
361
|
a = @m_author.create { |rec|
|
349
362
|
rec.id = 9
|
350
363
|
rec.name = 'author9'
|
@@ -353,11 +366,11 @@ describe 'A DBI::Model subclass' do
|
|
353
366
|
a.class.should.equal @m_author
|
354
367
|
a.id.should.equal 9
|
355
368
|
a.name.should.equal 'author9'
|
356
|
-
|
369
|
+
|
357
370
|
a_ = @m_author[ 9 ]
|
358
371
|
a_.should.equal a
|
359
372
|
a_.name.should.equal 'author9'
|
360
|
-
|
373
|
+
|
361
374
|
m = nil
|
362
375
|
should.not.raise do
|
363
376
|
m = @m_mc.create { |rec|
|
@@ -373,10 +386,10 @@ describe 'A DBI::Model subclass' do
|
|
373
386
|
m_.c3.should.equal 8
|
374
387
|
m_.c4.should.be.nil
|
375
388
|
m_.c5.should.be.nil
|
376
|
-
|
389
|
+
|
377
390
|
reset_data
|
378
391
|
end
|
379
|
-
|
392
|
+
|
380
393
|
it 'returns a record via #find_or_create( Hash )' do
|
381
394
|
n = @m_author.count
|
382
395
|
a = @m_author.find_or_create(
|
@@ -390,7 +403,7 @@ describe 'A DBI::Model subclass' do
|
|
390
403
|
a.should.not.respond_to :no_column_by_this_name
|
391
404
|
a.name.should.equal 'author1'
|
392
405
|
@m_author.count.should.equal n
|
393
|
-
|
406
|
+
|
394
407
|
n = @m_mc.count
|
395
408
|
row = @m_mc.find_or_create( :c1 => 100, :c2 => nil )
|
396
409
|
row.should.not.be.nil
|
@@ -399,7 +412,7 @@ describe 'A DBI::Model subclass' do
|
|
399
412
|
row.c3.should.equal 40
|
400
413
|
@m_mc.count.should.equal n
|
401
414
|
end
|
402
|
-
|
415
|
+
|
403
416
|
it 'creates a record via #find_or_create( Hash )' do
|
404
417
|
n = @m_author.count
|
405
418
|
a = @m_author.find_or_create(
|
@@ -413,15 +426,15 @@ describe 'A DBI::Model subclass' do
|
|
413
426
|
a.should.not.respond_to :no_column_by_this_name
|
414
427
|
a.name.should.equal 'author9'
|
415
428
|
@m_author.count.should.equal n+1
|
416
|
-
|
429
|
+
|
417
430
|
a_ = @m_author[ 9 ]
|
418
431
|
a_.should.not.be.nil
|
419
432
|
a_.should.equal a
|
420
433
|
a_.name.should.equal 'author9'
|
421
|
-
|
434
|
+
|
422
435
|
reset_data
|
423
436
|
end
|
424
|
-
|
437
|
+
|
425
438
|
it 'provides a means to use generic raw SQL to select model instances' do
|
426
439
|
posts = @m_post.s(
|
427
440
|
%{
|
@@ -439,19 +452,19 @@ describe 'A DBI::Model subclass' do
|
|
439
452
|
posts.should.not.be.nil
|
440
453
|
posts.should.not.be.empty
|
441
454
|
posts.size.should.equal 2
|
442
|
-
|
455
|
+
|
443
456
|
posts[ 0 ].id.should.equal 1
|
444
457
|
posts[ 0 ].text.should.equal 'First post.'
|
445
458
|
posts[ 0 ].class.should.equal @m_post
|
446
459
|
posts[ 1 ].id.should.equal 3
|
447
460
|
posts[ 1 ].text.should.equal 'Third post.'
|
448
461
|
posts[ 1 ].class.should.equal @m_post
|
449
|
-
|
462
|
+
|
450
463
|
no_posts = @m_post.s( "SELECT * FROM posts WHERE 1+1 = 3" )
|
451
464
|
no_posts.should.not.be.nil
|
452
465
|
no_posts.should.be.empty
|
453
466
|
end
|
454
|
-
|
467
|
+
|
455
468
|
it 'provides a means to use generic raw SQL to select one model instance' do
|
456
469
|
post = @m_post.s1(
|
457
470
|
%{
|
@@ -468,18 +481,18 @@ describe 'A DBI::Model subclass' do
|
|
468
481
|
},
|
469
482
|
'author1'
|
470
483
|
)
|
471
|
-
|
484
|
+
|
472
485
|
post.should.not.be.nil
|
473
486
|
post.class.should.equal @m_post
|
474
|
-
|
487
|
+
|
475
488
|
post.id.should.equal 3
|
476
489
|
post.author_id.should.equal 1
|
477
490
|
post.text.should.equal 'Third post.'
|
478
|
-
|
491
|
+
|
479
492
|
no_post = @m_post.s1( "SELECT * FROM posts WHERE 1+1 = 3" )
|
480
493
|
no_post.should.be.nil
|
481
494
|
end
|
482
|
-
|
495
|
+
|
483
496
|
it 'is Enumerable' do
|
484
497
|
should.not.raise do
|
485
498
|
@m_author.each { |a| }
|
@@ -498,66 +511,66 @@ describe 'A DBI::Model subclass' do
|
|
498
511
|
authors.find { |a| a.name == 'author3' }.should.not.be.nil
|
499
512
|
authors.find { |a| a.name == 'author99' }.should.be.nil
|
500
513
|
end
|
501
|
-
|
514
|
+
|
502
515
|
it 'provides a means to update records referred to by primary key value' do
|
503
516
|
new_text = 'Some new text.'
|
504
|
-
|
517
|
+
|
505
518
|
p2 = @m_post[ 2 ]
|
506
519
|
p2.text.should.not.equal new_text
|
507
520
|
@m_post.update_one( 2, { :text => new_text } )
|
508
521
|
p2_ = @m_post[ 2 ]
|
509
522
|
p2_.text.should.equal new_text
|
510
|
-
|
523
|
+
|
511
524
|
row = @m_mcpk[ 1, 1 ]
|
512
525
|
row.val.should.not.equal new_text
|
513
526
|
@m_mcpk.update_one( 1, 1, { :val => new_text } )
|
514
527
|
row = @m_mcpk[ 1, 1 ]
|
515
528
|
row.val.should.equal new_text
|
516
|
-
|
529
|
+
|
517
530
|
row = @m_mcpk[ 3, 4 ]
|
518
531
|
row.val.should.not.equal new_text
|
519
532
|
@m_mcpk.update_one( 3, 4, { :val => new_text } )
|
520
533
|
row = @m_mcpk[ 3, 4 ]
|
521
534
|
row.val.should.equal new_text
|
522
|
-
|
535
|
+
|
523
536
|
reset_data
|
524
537
|
end
|
525
|
-
|
538
|
+
|
526
539
|
it 'provides a means to update records referred to by a value hash' do
|
527
540
|
new_text = 'This is some new text.'
|
528
|
-
|
541
|
+
|
529
542
|
posts = @m_post.where( :author_id => 1 )
|
530
543
|
posts.size.should.equal 2
|
531
544
|
posts.find_all { |p| p.text == new_text }.should.be.empty
|
532
|
-
|
545
|
+
|
533
546
|
@m_post.update(
|
534
547
|
{ :author_id => 1 },
|
535
548
|
{ :text => new_text }
|
536
549
|
)
|
537
|
-
|
550
|
+
|
538
551
|
posts_ = @m_post.where( :author_id => 1 )
|
539
552
|
posts_.size.should.equal 2
|
540
553
|
posts_.find_all { |p| p.text == new_text }.should.equal posts_
|
541
|
-
|
554
|
+
|
542
555
|
reset_data
|
543
556
|
end
|
544
|
-
|
557
|
+
|
545
558
|
it 'provides a means to update records specified by a raw WHERE clause' do
|
546
559
|
new_text = 'This is some new text.'
|
547
|
-
|
560
|
+
|
548
561
|
posts = @m_post.where( :author_id => 1 )
|
549
562
|
posts.size.should.equal 2
|
550
563
|
posts.find_all { |p| p.text == new_text }.should.be.empty
|
551
|
-
|
564
|
+
|
552
565
|
@m_post.update(
|
553
566
|
"author_id < 2",
|
554
567
|
{ :text => new_text }
|
555
568
|
)
|
556
|
-
|
569
|
+
|
557
570
|
posts_ = @m_post.where( :author_id => 1 )
|
558
571
|
posts_.size.should.equal 2
|
559
572
|
posts_.find_all { |p| p.text == new_text }.should.equal posts_
|
560
|
-
|
573
|
+
|
561
574
|
reset_data
|
562
575
|
end
|
563
576
|
end
|
@@ -568,7 +581,7 @@ describe 'A created DBI::Model subclass instance' do
|
|
568
581
|
@m_author = Class.new( DBI::Model( :authors ) )
|
569
582
|
@m_post = Class.new( DBI::Model( :posts ) )
|
570
583
|
end
|
571
|
-
|
584
|
+
|
572
585
|
it 'provides read access to fields via identically-named readers' do
|
573
586
|
mc = @m_mc.create(
|
574
587
|
:c3 => 3,
|
@@ -585,7 +598,7 @@ describe 'A created DBI::Model subclass instance' do
|
|
585
598
|
mc.c3.should.equal 3
|
586
599
|
mc.c4.should.equal 4
|
587
600
|
end
|
588
|
-
|
601
|
+
|
589
602
|
it 'provides write access to fields via identically-named writers' do
|
590
603
|
mc = @m_mc.create(
|
591
604
|
:c3 => 30,
|
@@ -600,7 +613,7 @@ describe 'A created DBI::Model subclass instance' do
|
|
600
613
|
mc.c4.should.equal 40
|
601
614
|
id_ = mc.id
|
602
615
|
id_.should.not.be.nil
|
603
|
-
|
616
|
+
|
604
617
|
mc_ = @m_mc[ id_ ]
|
605
618
|
mc_.id.should.equal id_
|
606
619
|
mc_.c1.should.equal 10
|
@@ -608,25 +621,25 @@ describe 'A created DBI::Model subclass instance' do
|
|
608
621
|
mc_.c3.should.equal 30
|
609
622
|
mc_.c4.should.equal 40
|
610
623
|
end
|
611
|
-
|
624
|
+
|
612
625
|
it 'maintains Hash key equality across different fetches' do
|
613
626
|
h = Hash.new
|
614
627
|
a = @m_author[ 1 ]
|
615
628
|
h[ a ] = 123
|
616
629
|
a_ = @m_author[ 1 ]
|
617
630
|
h[ a_].should.equal 123
|
618
|
-
|
631
|
+
|
619
632
|
a2 = @m_author[ 2 ]
|
620
633
|
h[ a2 ].should.be.nil
|
621
|
-
|
634
|
+
|
622
635
|
h[ a2 ] = 456
|
623
636
|
h[ a ].should.equal 123
|
624
637
|
h[ a_ ].should.equal 123
|
625
|
-
|
638
|
+
|
626
639
|
a2_ = @m_author[ 2 ]
|
627
640
|
h[ a2_ ].should.equal 456
|
628
641
|
end
|
629
|
-
|
642
|
+
|
630
643
|
it 'maintains Hash key distinction for different Model subclasses' do
|
631
644
|
h = Hash.new
|
632
645
|
a = @m_author[ 1 ]
|
@@ -634,7 +647,7 @@ describe 'A created DBI::Model subclass instance' do
|
|
634
647
|
p = @m_post[ 1 ]
|
635
648
|
h[ p ] = 456
|
636
649
|
h[ p ].should.equal 456
|
637
|
-
|
650
|
+
|
638
651
|
a_ = @m_author[ 1 ]
|
639
652
|
h[ a_ ].should.equal 123
|
640
653
|
end
|
@@ -645,57 +658,58 @@ describe 'A found DBI::Model subclass instance' do
|
|
645
658
|
@m_author = Class.new( DBI::Model( :authors ) )
|
646
659
|
@m_post = Class.new( DBI::Model( :posts ) )
|
647
660
|
@m_mc = Class.new( DBI::Model( :many_col_table ) )
|
661
|
+
@m_nipk = Class.new( DBI::Model( :non_id_pk, [ :str ] ) )
|
648
662
|
@m_mcpk = Class.new( DBI::Model( :mcpk, [ :kc1, :kc2 ] ) )
|
649
663
|
end
|
650
|
-
|
664
|
+
|
651
665
|
it 'provides access to primary key value' do
|
652
666
|
a = @m_author[ 1 ]
|
653
667
|
a.pk.should.equal 1
|
654
|
-
|
668
|
+
|
655
669
|
p = @m_post[ 3 ]
|
656
670
|
p.pk.should.equal 3
|
657
|
-
|
671
|
+
|
658
672
|
r = @m_mcpk[ 1, 1 ]
|
659
673
|
r.pk.should.equal [ 1, 1 ]
|
660
|
-
|
674
|
+
|
661
675
|
r = @m_mcpk[ { :kc1 => 3, :kc2 => 4 } ]
|
662
676
|
r.pk.should.equal [ 3, 4 ]
|
663
677
|
end
|
664
|
-
|
678
|
+
|
665
679
|
it 'provides read access to fields via identically-named readers' do
|
666
680
|
p = @m_post[ 2 ]
|
667
|
-
|
681
|
+
|
668
682
|
should.not.raise( NoMethodError ) do
|
669
683
|
p.id
|
670
684
|
p.author_id
|
671
685
|
p.text
|
672
686
|
end
|
673
|
-
|
687
|
+
|
674
688
|
should.raise( NoMethodError ) do
|
675
689
|
p.foobar
|
676
690
|
end
|
677
|
-
|
691
|
+
|
678
692
|
p.id.should.equal 2
|
679
693
|
p.author_id.should.equal 2
|
680
694
|
p.text.should.equal 'Second post.'
|
681
695
|
end
|
682
|
-
|
696
|
+
|
683
697
|
it 'provides write access to fields via identically-named writers' do
|
684
698
|
the_new_text = 'Here is some new text.'
|
685
|
-
|
699
|
+
|
686
700
|
p2 = @m_post[ 2 ]
|
687
|
-
|
701
|
+
|
688
702
|
p3 = @m_post[ 3 ]
|
689
703
|
p3.text = the_new_text
|
690
704
|
p3.text.should.equal the_new_text
|
691
|
-
|
705
|
+
|
692
706
|
p3_ = @m_post[ 3 ]
|
693
707
|
p3_.text.should.equal the_new_text
|
694
|
-
|
708
|
+
|
695
709
|
# Shouldn't change other rows
|
696
710
|
p2_ = @m_post[ 2 ]
|
697
711
|
p2_.text.should.equal p2.text
|
698
|
-
|
712
|
+
|
699
713
|
mc1 = @m_mc.create(
|
700
714
|
:id => 1,
|
701
715
|
:c1 => 2
|
@@ -705,17 +719,17 @@ describe 'A found DBI::Model subclass instance' do
|
|
705
719
|
mc1.c1.should.be.nil
|
706
720
|
mc1_ = @m_mc[ 1 ]
|
707
721
|
mc1_.c1.should.be.nil
|
708
|
-
|
722
|
+
|
709
723
|
reset_data
|
710
724
|
end
|
711
|
-
|
725
|
+
|
712
726
|
it 'maintains identity across multiple DB hits' do
|
713
727
|
px = @m_post[ 1 ]
|
714
728
|
py = @m_post[ 1 ]
|
715
|
-
|
729
|
+
|
716
730
|
px.should.equal py
|
717
731
|
end
|
718
|
-
|
732
|
+
|
719
733
|
it 'provides multi-column writability via Model#set' do
|
720
734
|
p = @m_post[ 1 ]
|
721
735
|
the_new_text = 'The 3rd post.'
|
@@ -725,11 +739,11 @@ describe 'A found DBI::Model subclass instance' do
|
|
725
739
|
)
|
726
740
|
p.author_id.should.equal 2
|
727
741
|
p.text.should.equal the_new_text
|
728
|
-
|
742
|
+
|
729
743
|
p_ = @m_post[ 1 ]
|
730
744
|
p_.author_id.should.equal 2
|
731
745
|
p_.text.should.equal the_new_text
|
732
|
-
|
746
|
+
|
733
747
|
mc1 = @m_mc.create(
|
734
748
|
:id => 1,
|
735
749
|
:c1 => 2,
|
@@ -744,17 +758,23 @@ describe 'A found DBI::Model subclass instance' do
|
|
744
758
|
mc1_ = @m_mc[ 1 ]
|
745
759
|
mc1_.c1.should.be.nil
|
746
760
|
mc1_.c2.should.equal 4
|
747
|
-
|
761
|
+
|
748
762
|
reset_data
|
749
763
|
end
|
750
|
-
|
764
|
+
|
751
765
|
it 'is deleted by #delete' do
|
752
766
|
p = @m_post[ 3 ]
|
753
767
|
p.should.not.be.nil
|
754
768
|
successfully_deleted = p.delete
|
755
769
|
successfully_deleted.should.be.true
|
756
770
|
@m_post[ 3 ].should.be.nil
|
757
|
-
|
771
|
+
|
772
|
+
o = @m_nipk[ 'one' ]
|
773
|
+
o.should.not.be.nil
|
774
|
+
successfully_deleted = o.delete
|
775
|
+
successfully_deleted.should.be.true
|
776
|
+
@m_nipk[ 'one' ].should.be.nil
|
777
|
+
|
758
778
|
reset_data
|
759
779
|
end
|
760
780
|
|
@@ -764,7 +784,7 @@ describe 'A found DBI::Model subclass instance' do
|
|
764
784
|
p.save
|
765
785
|
end
|
766
786
|
end
|
767
|
-
|
787
|
+
|
768
788
|
end
|
769
789
|
|
770
790
|
describe 'DBI::Model (relationships)' do
|
@@ -773,7 +793,7 @@ describe 'DBI::Model (relationships)' do
|
|
773
793
|
@m_post = Class.new( DBI::Model( :posts ) )
|
774
794
|
@m_fan = Class.new( DBI::Model( :fans ) )
|
775
795
|
end
|
776
|
-
|
796
|
+
|
777
797
|
it 'facilitates relating one to many, providing read access' do
|
778
798
|
DBI::Model.one_to_many( @m_author, @m_post, :posts, :author, :author_id )
|
779
799
|
a = @m_author[ 1 ]
|
@@ -782,7 +802,7 @@ describe 'DBI::Model (relationships)' do
|
|
782
802
|
p.author.should.not.be.nil
|
783
803
|
p.author.id.should.equal 1
|
784
804
|
end
|
785
|
-
|
805
|
+
|
786
806
|
it 'facilitates relating one to many, allowing one of the many to set its one' do
|
787
807
|
DBI::Model.one_to_many(
|
788
808
|
@m_author, @m_post, :posts, :author, :author_id
|
@@ -793,10 +813,10 @@ describe 'DBI::Model (relationships)' do
|
|
793
813
|
p.author = @m_author.create( :id => 4, :name => 'author4' )
|
794
814
|
p_ = @m_post[ 3 ]
|
795
815
|
p_.author.id.should.equal 4
|
796
|
-
|
816
|
+
|
797
817
|
reset_data
|
798
818
|
end
|
799
|
-
|
819
|
+
|
800
820
|
it 'facilitates relating many to many, providing read access' do
|
801
821
|
DBI::Model.many_to_many(
|
802
822
|
@m_author, @m_fan, :authors_liked, :fans, :authors_fans, :author_id, :fan_id
|
@@ -805,7 +825,7 @@ describe 'DBI::Model (relationships)' do
|
|
805
825
|
a2 = @m_author[ 2 ]
|
806
826
|
f2 = @m_fan[ 2 ]
|
807
827
|
f3 = @m_fan[ 3 ]
|
808
|
-
|
828
|
+
|
809
829
|
a1f = a1.fans
|
810
830
|
a1f.should.not.be.nil
|
811
831
|
a1f.should.not.be.empty
|
@@ -814,7 +834,7 @@ describe 'DBI::Model (relationships)' do
|
|
814
834
|
a1f.find { |f| f.name == 'fan1' }.should.be.nil
|
815
835
|
a1f.find { |f| f.name == 'fan2' }.should.not.be.nil
|
816
836
|
a1f.find { |f| f.name == 'fan3' }.should.not.be.nil
|
817
|
-
|
837
|
+
|
818
838
|
a2f = a2.fans
|
819
839
|
a2f.should.not.be.nil
|
820
840
|
a2f.should.not.be.empty
|
@@ -823,14 +843,14 @@ describe 'DBI::Model (relationships)' do
|
|
823
843
|
a2f.find { |f| f.name == 'fan1' }.should.be.nil
|
824
844
|
a2f.find { |f| f.name == 'fan3' }.should.not.be.nil
|
825
845
|
a2f.find { |f| f.name == 'fan4' }.should.not.be.nil
|
826
|
-
|
846
|
+
|
827
847
|
f2a = f2.authors_liked
|
828
848
|
f2a.should.not.be.nil
|
829
849
|
f2a.should.not.be.empty
|
830
850
|
f2a.size.should.equal 1
|
831
851
|
f2a[ 0 ].class.should.equal @m_author
|
832
852
|
f2a[ 0 ].name.should.equal 'author1'
|
833
|
-
|
853
|
+
|
834
854
|
f3a = f3.authors_liked
|
835
855
|
f3a.should.not.be.nil
|
836
856
|
f3a.should.not.be.empty
|
@@ -838,7 +858,7 @@ describe 'DBI::Model (relationships)' do
|
|
838
858
|
f3a.find { |a| a.name == 'author1' }.should.not.be.nil
|
839
859
|
f3a.find { |a| a.name == 'author2' }.should.not.be.nil
|
840
860
|
f3a.find { |a| a.name == 'author3' }.should.be.nil
|
841
|
-
|
861
|
+
|
842
862
|
@m_author[ 3 ].fans.should.be.empty
|
843
863
|
@m_fan[ 5 ].authors_liked.should.be.empty
|
844
864
|
end
|
@@ -848,12 +868,12 @@ describe 'DBI::Collection' do
|
|
848
868
|
before do
|
849
869
|
@m_author = Class.new( DBI::Model( :authors ) )
|
850
870
|
@m_post = Class.new( DBI::Model( :posts ) )
|
851
|
-
|
871
|
+
|
852
872
|
DBI::Model.one_to_many(
|
853
873
|
@m_author, @m_post, :posts, :author, :author_id
|
854
874
|
)
|
855
875
|
end
|
856
|
-
|
876
|
+
|
857
877
|
it 'accepts additions' do
|
858
878
|
a = @m_author[ 1 ]
|
859
879
|
the_text = 'A new post.'
|
@@ -861,26 +881,26 @@ describe 'DBI::Collection' do
|
|
861
881
|
p = a.posts.find { |p| p.text == the_text }
|
862
882
|
p.should.not.be.nil
|
863
883
|
p.author.should.equal a
|
864
|
-
|
884
|
+
|
865
885
|
a_ = @m_author[ 1 ]
|
866
886
|
a_.posts.find { |p| p.text == the_text }.should.not.be.nil
|
867
|
-
|
887
|
+
|
868
888
|
reset_data
|
869
889
|
end
|
870
|
-
|
890
|
+
|
871
891
|
it 'facilitates single record deletions' do
|
872
892
|
a = @m_author[ 1 ]
|
873
893
|
posts = a.posts
|
874
894
|
n = posts.size
|
875
895
|
p = posts[ 0 ]
|
876
|
-
|
896
|
+
|
877
897
|
posts.delete( p ).should.be.true
|
878
898
|
a.posts.size.should.equal( n - 1 )
|
879
899
|
posts.find { |p_| p_ == p }.should.be.nil
|
880
|
-
|
900
|
+
|
881
901
|
reset_data
|
882
902
|
end
|
883
|
-
|
903
|
+
|
884
904
|
it 'facilitates multi-record deletions' do
|
885
905
|
a = @m_author[ 1 ]
|
886
906
|
posts = a.posts
|
@@ -889,16 +909,16 @@ describe 'DBI::Collection' do
|
|
889
909
|
a.posts.size.should.equal( n - 1 )
|
890
910
|
posts.find { |p| p.text == 'Third post.' }.should.be.nil
|
891
911
|
posts.find { |p| p.text == 'First post.' }.should.not.be.nil
|
892
|
-
|
912
|
+
|
893
913
|
reset_data
|
894
914
|
end
|
895
|
-
|
915
|
+
|
896
916
|
it 'facilitates table-wide deletion' do
|
897
917
|
a = @m_author[ 1 ]
|
898
918
|
a.posts.should.not.be.empty
|
899
919
|
a.posts.clear.should.be > 0
|
900
920
|
a.posts.should.be.empty
|
901
|
-
|
921
|
+
|
902
922
|
reset_data
|
903
923
|
end
|
904
924
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: m4dbi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pistos
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-02-08 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -83,7 +83,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
83
83
|
requirements:
|
84
84
|
- bacon (optional)
|
85
85
|
rubyforge_project: m4dbi
|
86
|
-
rubygems_version: 1.
|
86
|
+
rubygems_version: 1.3.1
|
87
87
|
signing_key:
|
88
88
|
specification_version: 2
|
89
89
|
summary: Models (and More) for DBI
|