m4dbi 0.6.0 → 0.6.1
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/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
|