lafcadio 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/lafcadio_schema +12 -4
- data/lib/lafcadio.rb +1 -1
- data/lib/lafcadio.rb~ +1 -1
- data/lib/lafcadio/depend.rb +2 -0
- data/lib/lafcadio/domain.rb +49 -34
- data/lib/lafcadio/domain.rb~ +50 -28
- data/lib/lafcadio/mock.rb +12 -9
- data/lib/lafcadio/objectField.rb +66 -130
- data/lib/lafcadio/objectStore.rb +106 -95
- data/lib/lafcadio/query.rb +87 -78
- data/lib/lafcadio/schema.rb +0 -1
- data/lib/lafcadio/test.rb +4 -1
- data/lib/lafcadio/test/testconfig.dat +0 -2
- data/lib/lafcadio/test/testconfig.dat~ +13 -0
- data/lib/lafcadio/util.rb +2 -120
- data/lib/lafcadio/util.rb~ +379 -0
- metadata +14 -10
- data/lib/lafcadio/TestSuite.rb +0 -18
- data/lib/lafcadio/TestSuite.rb~ +0 -16
- data/lib/lafcadio/dateTime.rb~ +0 -93
- data/lib/lafcadio/mock.rb~ +0 -93
- data/lib/lafcadio/objectField.rb~ +0 -618
- data/lib/lafcadio/objectStore.rb~ +0 -746
- data/lib/lafcadio/query.rb~ +0 -572
- data/lib/lafcadio/test.rb~ +0 -17
data/lib/lafcadio/objectField.rb
CHANGED
@@ -7,8 +7,8 @@ module Lafcadio
|
|
7
7
|
class ObjectField
|
8
8
|
include Comparable
|
9
9
|
|
10
|
-
attr_reader :name, :
|
11
|
-
attr_accessor :not_null, :
|
10
|
+
attr_reader :name, :domain_class
|
11
|
+
attr_accessor :not_null, :db_field_name
|
12
12
|
|
13
13
|
def self.instantiate_from_xml( domain_class, fieldElt ) #:nodoc:
|
14
14
|
parameters = instantiation_parameters( fieldElt )
|
@@ -16,8 +16,7 @@ module Lafcadio
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
19
|
-
instance = self.new( domain_class, parameters['name']
|
20
|
-
parameters['english_name'] )
|
19
|
+
instance = self.new( domain_class, parameters['name'] )
|
21
20
|
if ( db_field_name = parameters['db_field_name'] )
|
22
21
|
instance.db_field_name = db_field_name
|
23
22
|
end
|
@@ -27,7 +26,6 @@ module Lafcadio
|
|
27
26
|
def self.instantiation_parameters( fieldElt ) #:nodoc:
|
28
27
|
parameters = {}
|
29
28
|
parameters['name'] = fieldElt.attributes['name']
|
30
|
-
parameters['english_name'] = fieldElt.attributes['english_name']
|
31
29
|
parameters['db_field_name'] = fieldElt.attributes['db_field_name']
|
32
30
|
parameters
|
33
31
|
end
|
@@ -36,20 +34,17 @@ module Lafcadio
|
|
36
34
|
Object
|
37
35
|
end
|
38
36
|
|
39
|
-
# [
|
40
|
-
# [name]
|
41
|
-
|
42
|
-
|
43
|
-
@object_type = object_type
|
37
|
+
# [domain_class] The domain class that this object field belongs to.
|
38
|
+
# [name] The name of this field.
|
39
|
+
def initialize( domain_class, name )
|
40
|
+
@domain_class = domain_class
|
44
41
|
@name = name
|
45
42
|
@db_field_name = name
|
46
43
|
@not_null = true
|
47
|
-
@unique = false
|
48
|
-
@english_nameOrNil = english_name
|
49
44
|
end
|
50
45
|
|
51
46
|
def <=>(other)
|
52
|
-
if @
|
47
|
+
if @domain_class == other.domain_class && name == other.name
|
53
48
|
0
|
54
49
|
else
|
55
50
|
object_id <=> other.object_id
|
@@ -59,17 +54,13 @@ module Lafcadio
|
|
59
54
|
def bind_write?; false; end #:nodoc:
|
60
55
|
|
61
56
|
def db_table_and_field_name
|
62
|
-
"#{
|
57
|
+
"#{ domain_class.table_name }.#{ db_field_name }"
|
63
58
|
end
|
64
59
|
|
65
60
|
def db_will_automatically_write #:nodoc:
|
66
61
|
false
|
67
62
|
end
|
68
63
|
|
69
|
-
def english_name #:nodoc:
|
70
|
-
@english_nameOrNil || English.camel_case_to_english(name).capitalize
|
71
|
-
end
|
72
|
-
|
73
64
|
# Returns the name that this field is referenced by in the MySQL table. By
|
74
65
|
# default this is the same as the name; to override it, set
|
75
66
|
# ObjectField#db_field_name.
|
@@ -77,12 +68,8 @@ module Lafcadio
|
|
77
68
|
db_field_name
|
78
69
|
end
|
79
70
|
|
80
|
-
def null_error_msg #:nodoc:
|
81
|
-
"#{ self.object_type.name }##{ name } can not be nil."
|
82
|
-
end
|
83
|
-
|
84
71
|
def prev_value(pk_id) #:nodoc:
|
85
|
-
prevObject = ObjectStore.get_object_store.get(@
|
72
|
+
prevObject = ObjectStore.get_object_store.get( @domain_class, pk_id )
|
86
73
|
prevObject.send(name)
|
87
74
|
end
|
88
75
|
|
@@ -99,7 +86,11 @@ module Lafcadio
|
|
99
86
|
|
100
87
|
def verify(value, pk_id) #:nodoc:
|
101
88
|
if value.nil? && not_null
|
102
|
-
raise
|
89
|
+
raise(
|
90
|
+
FieldValueError,
|
91
|
+
"#{ self.domain_class.name }##{ name } can not be nil.",
|
92
|
+
caller
|
93
|
+
)
|
103
94
|
end
|
104
95
|
verify_non_nil( value, pk_id ) if value
|
105
96
|
end
|
@@ -107,23 +98,12 @@ module Lafcadio
|
|
107
98
|
def verify_non_nil( value, pk_id )
|
108
99
|
value_type = self.class.value_type
|
109
100
|
unless value.class <= value_type
|
110
|
-
raise(
|
111
|
-
|
101
|
+
raise(
|
102
|
+
FieldValueError,
|
103
|
+
"#{ domain_class.name }##{ name } needs a " + value_type.name +
|
112
104
|
" value.",
|
113
|
-
|
114
|
-
|
115
|
-
verify_uniqueness(value, pk_id) if unique
|
116
|
-
end
|
117
|
-
|
118
|
-
def verify_uniqueness(value, pk_id) #:nodoc:
|
119
|
-
inferrer = Query::Inferrer.new( @object_type ) { |domain_obj|
|
120
|
-
Query.And( domain_obj.send( self.name ).equals( value ),
|
121
|
-
domain_obj.pk_id.equals( pk_id ).not )
|
122
|
-
}
|
123
|
-
collisions = ObjectStore.get_object_store.get_subset( inferrer.execute )
|
124
|
-
if collisions.size > 0
|
125
|
-
notUniqueMsg = "That #{english_name.downcase} already exists."
|
126
|
-
raise FieldValueError, notUniqueMsg, caller
|
105
|
+
caller
|
106
|
+
)
|
127
107
|
end
|
128
108
|
end
|
129
109
|
|
@@ -154,28 +134,6 @@ module Lafcadio
|
|
154
134
|
end
|
155
135
|
end
|
156
136
|
|
157
|
-
class AutoIncrementField < IntegerField # :nodoc:
|
158
|
-
attr_reader :object_type
|
159
|
-
|
160
|
-
def initialize(object_type, name, english_name = nil)
|
161
|
-
super(object_type, name, english_name)
|
162
|
-
@object_type = object_type
|
163
|
-
end
|
164
|
-
|
165
|
-
def html_widget_value_str(value)
|
166
|
-
if value != nil
|
167
|
-
super value
|
168
|
-
else
|
169
|
-
highestValue = 0
|
170
|
-
ObjectStore.get_object_store.get_all(object_type).each { |obj|
|
171
|
-
aValue = obj.send(name).to_i
|
172
|
-
highestValue = aValue if aValue > highestValue
|
173
|
-
}
|
174
|
-
(highestValue + 1).to_s
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
137
|
# BlobField stores a string value and expects to store its value in a BLOB
|
180
138
|
# field in the database.
|
181
139
|
class BlobField < ObjectField
|
@@ -220,8 +178,8 @@ module Lafcadio
|
|
220
178
|
|
221
179
|
attr_accessor :enum_type, :enums
|
222
180
|
|
223
|
-
def initialize(
|
224
|
-
super(
|
181
|
+
def initialize( domain_class, name )
|
182
|
+
super( domain_class, name )
|
225
183
|
@enum_type = ENUMS_ONE_ZERO
|
226
184
|
@enums = nil
|
227
185
|
end
|
@@ -270,18 +228,12 @@ module Lafcadio
|
|
270
228
|
|
271
229
|
# DateField represents a Date.
|
272
230
|
class DateField < ObjectField
|
273
|
-
RANGE_NEAR_FUTURE = 0
|
274
|
-
RANGE_PAST = 1
|
275
|
-
|
276
231
|
def self.value_type # :nodoc:
|
277
232
|
Date
|
278
233
|
end
|
279
234
|
|
280
|
-
|
281
|
-
|
282
|
-
def initialize(object_type, name = "date", english_name = nil)
|
283
|
-
super(object_type, name, english_name)
|
284
|
-
@range = RANGE_NEAR_FUTURE
|
235
|
+
def initialize( domain_class, name = "date" )
|
236
|
+
super( domain_class, name )
|
285
237
|
end
|
286
238
|
|
287
239
|
def value_for_sql(value) # :nodoc:
|
@@ -321,7 +273,7 @@ module Lafcadio
|
|
321
273
|
# DecimalField represents a decimal value.
|
322
274
|
class DecimalField < ObjectField
|
323
275
|
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
324
|
-
self.new( domain_class, parameters['name']
|
276
|
+
self.new( domain_class, parameters['name'] )
|
325
277
|
end
|
326
278
|
|
327
279
|
def self.value_type #:nodoc:
|
@@ -346,20 +298,18 @@ module Lafcadio
|
|
346
298
|
address =~ /^[^ @]+@[^ \.]+\.[^ ,]+$/
|
347
299
|
end
|
348
300
|
|
349
|
-
def initialize(
|
350
|
-
super(
|
351
|
-
end
|
352
|
-
|
353
|
-
def null_error_msg #:nodoc:
|
354
|
-
"Please enter an email address."
|
301
|
+
def initialize( domain_class, name = "email" )
|
302
|
+
super( domain_class, name )
|
355
303
|
end
|
356
304
|
|
357
305
|
def verify_non_nil(value, pk_id) #:nodoc:
|
358
306
|
super(value, pk_id)
|
359
307
|
if !EmailField.valid_address(value)
|
360
|
-
raise(
|
361
|
-
|
362
|
-
|
308
|
+
raise(
|
309
|
+
FieldValueError,
|
310
|
+
"#{ domain_class.name }##{ name } needs a valid email address.",
|
311
|
+
caller
|
312
|
+
)
|
363
313
|
end
|
364
314
|
end
|
365
315
|
end
|
@@ -379,8 +329,7 @@ module Lafcadio
|
|
379
329
|
#
|
380
330
|
class EnumField < TextField
|
381
331
|
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
382
|
-
self.new( domain_class, parameters['name'], parameters['enums']
|
383
|
-
parameters['english_name'] )
|
332
|
+
self.new( domain_class, parameters['name'], parameters['enums'] )
|
384
333
|
end
|
385
334
|
|
386
335
|
def self.enum_queue_hash( fieldElt )
|
@@ -407,13 +356,12 @@ module Lafcadio
|
|
407
356
|
|
408
357
|
attr_reader :enums
|
409
358
|
|
410
|
-
# [
|
411
|
-
# [name]
|
412
|
-
# [enums]
|
413
|
-
#
|
414
|
-
|
415
|
-
|
416
|
-
super object_type, name, english_name
|
359
|
+
# [domain_class] The domain class that this field belongs to.
|
360
|
+
# [name] The name of this domain class.
|
361
|
+
# [enums] An array of Strings representing the possible choices for
|
362
|
+
# this field.
|
363
|
+
def initialize( domain_class, name, enums )
|
364
|
+
super( domain_class, name )
|
417
365
|
if enums.class == Array
|
418
366
|
@enums = QueueHash.new_from_array enums
|
419
367
|
else
|
@@ -430,7 +378,7 @@ module Lafcadio
|
|
430
378
|
if @enums[value].nil?
|
431
379
|
key_str = '[ ' +
|
432
380
|
( @enums.keys.map { |key| "\"#{ key }\"" } ).join(', ') + ' ]'
|
433
|
-
err_str = "#{ @
|
381
|
+
err_str = "#{ @domain_class.name }##{ name } needs a value that is " +
|
434
382
|
"one of #{ key_str }"
|
435
383
|
raise( FieldValueError, err_str, caller )
|
436
384
|
end
|
@@ -445,7 +393,7 @@ module Lafcadio
|
|
445
393
|
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
446
394
|
instance = self.new(
|
447
395
|
domain_class, parameters['linked_type'], parameters['name'],
|
448
|
-
parameters['
|
396
|
+
parameters['delete_cascade']
|
449
397
|
)
|
450
398
|
if parameters['db_field_name']
|
451
399
|
instance.db_field_name = parameters['db_field_name']
|
@@ -456,7 +404,7 @@ module Lafcadio
|
|
456
404
|
def self.instantiation_parameters( fieldElt ) #:nodoc:
|
457
405
|
parameters = super( fieldElt )
|
458
406
|
linked_typeStr = fieldElt.attributes['linked_type']
|
459
|
-
linked_type = DomainObject.
|
407
|
+
linked_type = DomainObject.get_domain_class_from_string( linked_typeStr )
|
460
408
|
parameters['linked_type'] = linked_type
|
461
409
|
parameters['delete_cascade'] = fieldElt.attributes['delete_cascade'] == 'y'
|
462
410
|
parameters
|
@@ -465,20 +413,20 @@ module Lafcadio
|
|
465
413
|
attr_reader :linked_type
|
466
414
|
attr_accessor :delete_cascade
|
467
415
|
|
468
|
-
# [
|
469
|
-
# [linked_type]
|
470
|
-
# [name]
|
471
|
-
# [
|
472
|
-
#
|
473
|
-
#
|
474
|
-
def initialize(
|
416
|
+
# [domain_class] The domain class that this field belongs to.
|
417
|
+
# [linked_type] The domain class that this field points to.
|
418
|
+
# [name] The name of this field.
|
419
|
+
# [delete_cascade] If this is true, deleting the domain object that is
|
420
|
+
# linked to will cause this domain object to be deleted
|
421
|
+
# as well.
|
422
|
+
def initialize( domain_class, linked_type, name = nil,
|
475
423
|
delete_cascade = false )
|
476
424
|
unless name
|
477
425
|
linked_type.name =~ /::/
|
478
426
|
name = $' || linked_type.name
|
479
427
|
name = name.decapitalize
|
480
428
|
end
|
481
|
-
super(
|
429
|
+
super( domain_class, name )
|
482
430
|
( @linked_type, @delete_cascade ) = linked_type, delete_cascade
|
483
431
|
end
|
484
432
|
|
@@ -499,7 +447,7 @@ module Lafcadio
|
|
499
447
|
|
500
448
|
def verify_non_nil(value, pk_id) #:nodoc:
|
501
449
|
super
|
502
|
-
if @linked_type != @
|
450
|
+
if @linked_type != @domain_class && pk_id
|
503
451
|
subsetLinkField = @linked_type.class_fields.find { |field|
|
504
452
|
field.class == SubsetLinkField && field.subset_field == @name
|
505
453
|
}
|
@@ -511,7 +459,7 @@ module Lafcadio
|
|
511
459
|
|
512
460
|
def verify_subset_link_field( subsetLinkField, pk_id )
|
513
461
|
begin
|
514
|
-
prevObj = ObjectStore.get_object_store.get(
|
462
|
+
prevObj = ObjectStore.get_object_store.get( domain_class, pk_id )
|
515
463
|
prevObjLinkedTo = prevObj.send(name)
|
516
464
|
possiblyMyObj = prevObjLinkedTo.send(subsetLinkField.name)
|
517
465
|
if possiblyMyObj && possiblyMyObj.pk_id == pk_id
|
@@ -524,9 +472,6 @@ module Lafcadio
|
|
524
472
|
end
|
525
473
|
end
|
526
474
|
|
527
|
-
class MoneyField < DecimalField #:nodoc:
|
528
|
-
end
|
529
|
-
|
530
475
|
# Accepts a Month as a value. This field automatically saves in MySQL as a
|
531
476
|
# date corresponding to the first day of the month.
|
532
477
|
class MonthField < DateField
|
@@ -539,19 +484,6 @@ module Lafcadio
|
|
539
484
|
end
|
540
485
|
end
|
541
486
|
|
542
|
-
# A PasswordField is simply a TextField that is expected to contain a password
|
543
|
-
# value. It can be set to auto-generate a password at random.
|
544
|
-
class PasswordField < TextField
|
545
|
-
# Returns a random 8-letter alphanumeric password.
|
546
|
-
def self.random_password
|
547
|
-
chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".
|
548
|
-
split(//)
|
549
|
-
value = ""
|
550
|
-
0.upto(8) { |i| value += chars[rand(chars.size)] }
|
551
|
-
value
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
487
|
class PrimaryKeyField < IntegerField
|
556
488
|
def initialize( domain_class )
|
557
489
|
super( domain_class, 'pk_id' )
|
@@ -563,16 +495,15 @@ module Lafcadio
|
|
563
495
|
# any of the 50 states of the United States, stored as each state's two-letter
|
564
496
|
# postal code.
|
565
497
|
class StateField < EnumField
|
566
|
-
def initialize(
|
567
|
-
super
|
498
|
+
def initialize( domain_class, name = "state" )
|
499
|
+
super( domain_class, name, UsStates.states )
|
568
500
|
end
|
569
501
|
end
|
570
502
|
|
571
503
|
class SubsetLinkField < LinkField #:nodoc:
|
572
504
|
def self.instantiate_with_parameters( domain_class, parameters )
|
573
505
|
self.new( domain_class, parameters['linked_type'],
|
574
|
-
parameters['subset_field'], parameters['name']
|
575
|
-
parameters['english_name'] )
|
506
|
+
parameters['subset_field'], parameters['name'] )
|
576
507
|
end
|
577
508
|
|
578
509
|
def self.instantiation_parameters( fieldElt )
|
@@ -583,9 +514,9 @@ module Lafcadio
|
|
583
514
|
|
584
515
|
attr_accessor :subset_field
|
585
516
|
|
586
|
-
def initialize(
|
587
|
-
|
588
|
-
super(
|
517
|
+
def initialize( domain_class, linked_type, subset_field,
|
518
|
+
name = linked_type.name.downcase )
|
519
|
+
super( domain_class, linked_type, name )
|
589
520
|
@subset_field = subset_field
|
590
521
|
end
|
591
522
|
end
|
@@ -600,7 +531,12 @@ module Lafcadio
|
|
600
531
|
end
|
601
532
|
|
602
533
|
def value_for_sql(objectValue) #:nodoc:
|
603
|
-
|
534
|
+
if objectValue.is_a?( Array )
|
535
|
+
str = objectValue.join(',')
|
536
|
+
else
|
537
|
+
str = objectValue
|
538
|
+
end
|
539
|
+
"'" + str + "'"
|
604
540
|
end
|
605
541
|
|
606
542
|
def value_from_sql(sqlString, lookupLink = true) #:nodoc:
|
@@ -613,8 +549,8 @@ module Lafcadio
|
|
613
549
|
end
|
614
550
|
|
615
551
|
class TimeStampField < DateTimeField #:nodoc:
|
616
|
-
def initialize(
|
617
|
-
super(
|
552
|
+
def initialize( domain_class, name = 'timeStamp' )
|
553
|
+
super( domain_class, name )
|
618
554
|
@not_null = false
|
619
555
|
end
|
620
556
|
|
data/lib/lafcadio/objectStore.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'dbi'
|
1
2
|
require 'lafcadio/domain'
|
2
3
|
require 'lafcadio/query'
|
3
4
|
require 'lafcadio/util'
|
@@ -51,7 +52,7 @@ module Lafcadio
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def update_dependent_domain_objects
|
54
|
-
dependent_classes = @db_object.
|
55
|
+
dependent_classes = @db_object.domain_class.dependent_classes
|
55
56
|
dependent_classes.keys.each { |aClass|
|
56
57
|
field = dependent_classes[aClass]
|
57
58
|
collection = @objectStore.get_filtered( aClass.name, @db_object,
|
@@ -68,7 +69,7 @@ module Lafcadio
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
class
|
72
|
+
class CouldntMatchDomainClassError < RuntimeError #:nodoc:
|
72
73
|
end
|
73
74
|
|
74
75
|
class DbBridge #:nodoc:
|
@@ -120,16 +121,16 @@ module Lafcadio
|
|
120
121
|
end
|
121
122
|
|
122
123
|
def get_collection_by_query(query)
|
123
|
-
|
124
|
+
domain_class = query.domain_class
|
124
125
|
execute_select( query.to_sql ).collect { |row_hash|
|
125
|
-
|
126
|
+
domain_class.new( SqlValueConverter.new( domain_class, row_hash ) )
|
126
127
|
}
|
127
128
|
end
|
128
129
|
|
129
130
|
def group_query( query )
|
130
131
|
execute_select( query.to_sql )[0].collect { |val|
|
131
|
-
if query.field_name != query.
|
132
|
-
a_field = query.
|
132
|
+
if query.field_name != query.domain_class.sql_primary_key_name
|
133
|
+
a_field = query.domain_class.get_field( query.field_name )
|
133
134
|
a_field.value_from_sql( val )
|
134
135
|
else
|
135
136
|
val.to_i
|
@@ -205,7 +206,8 @@ module Lafcadio
|
|
205
206
|
end
|
206
207
|
|
207
208
|
# The DomainObjectProxy is used when retrieving domain objects that are
|
208
|
-
# linked to other domain objects with LinkFields. In terms of +
|
209
|
+
# linked to other domain objects with LinkFields. In terms of +domain_class+
|
210
|
+
# and
|
209
211
|
# +pk_id+, a DomainObjectProxy instance looks to the outside world like the
|
210
212
|
# domain object it's supposed to represent. It only retrieves its domain
|
211
213
|
# object from the database when member data is requested.
|
@@ -213,20 +215,20 @@ module Lafcadio
|
|
213
215
|
# In normal usage you will probably never manipulate a DomainObjectProxy
|
214
216
|
# directly, but you may discover it by accident by calling
|
215
217
|
# DomainObjectProxy#class (or DomainObject#class) instead of
|
216
|
-
# DomainObjectProxy#
|
218
|
+
# DomainObjectProxy#domain_class (or DomainObjectProxy#domain_class).
|
217
219
|
class DomainObjectProxy
|
218
220
|
include DomainComparable
|
219
221
|
|
220
|
-
attr_accessor :
|
222
|
+
attr_accessor :domain_class, :pk_id
|
221
223
|
|
222
|
-
def initialize(
|
224
|
+
def initialize(domain_classOrDbObject, pk_id = nil)
|
223
225
|
if pk_id
|
224
|
-
@
|
226
|
+
@domain_class = domain_classOrDbObject
|
225
227
|
@pk_id = pk_id
|
226
|
-
elsif
|
227
|
-
@db_object =
|
228
|
+
elsif domain_classOrDbObject.class < DomainObject
|
229
|
+
@db_object = domain_classOrDbObject
|
228
230
|
@d_obj_retrieve_time = Time.now
|
229
|
-
@
|
231
|
+
@domain_class = @db_object.class
|
230
232
|
@pk_id = @db_object.pk_id
|
231
233
|
else
|
232
234
|
raise ArgumentError
|
@@ -237,9 +239,8 @@ module Lafcadio
|
|
237
239
|
def get_db_object
|
238
240
|
object_store = ObjectStore.get_object_store
|
239
241
|
if @db_object.nil? || needs_refresh?
|
240
|
-
@db_object = object_store.get(@
|
241
|
-
|
242
|
-
|
242
|
+
@db_object = object_store.get( @domain_class, @pk_id )
|
243
|
+
@d_obj_retrieve_time = Time.now
|
243
244
|
end
|
244
245
|
@db_object
|
245
246
|
end
|
@@ -254,7 +255,7 @@ module Lafcadio
|
|
254
255
|
|
255
256
|
def needs_refresh?
|
256
257
|
object_store = ObjectStore.get_object_store
|
257
|
-
last_commit_time = object_store.last_commit_time( @
|
258
|
+
last_commit_time = object_store.last_commit_time( @domain_class, @pk_id )
|
258
259
|
!last_commit_time.nil? && last_commit_time > @d_obj_retrieve_time
|
259
260
|
end
|
260
261
|
|
@@ -268,14 +269,14 @@ module Lafcadio
|
|
268
269
|
|
269
270
|
def initialize(obj); @obj = obj; end
|
270
271
|
|
271
|
-
def delete_sql(
|
272
|
-
"delete from #{
|
273
|
-
"where #{
|
272
|
+
def delete_sql( domain_class )
|
273
|
+
"delete from #{ domain_class.table_name} " +
|
274
|
+
"where #{ domain_class.sql_primary_key_name }=#{ @obj.pk_id }"
|
274
275
|
end
|
275
276
|
|
276
|
-
def get_name_value_pairs(
|
277
|
+
def get_name_value_pairs( domain_class )
|
277
278
|
nameValues = []
|
278
|
-
|
279
|
+
domain_class.class_fields.each { |field|
|
279
280
|
unless field.instance_of?( PrimaryKeyField )
|
280
281
|
value = @obj.send(field.name)
|
281
282
|
unless field.db_will_automatically_write
|
@@ -290,15 +291,15 @@ module Lafcadio
|
|
290
291
|
QueueHash.new( *nameValues )
|
291
292
|
end
|
292
293
|
|
293
|
-
def insert_sql(
|
294
|
-
fields =
|
295
|
-
nameValuePairs = get_name_value_pairs(
|
296
|
-
if
|
297
|
-
nameValuePairs[
|
294
|
+
def insert_sql( domain_class )
|
295
|
+
fields = domain_class.class_fields
|
296
|
+
nameValuePairs = get_name_value_pairs( domain_class )
|
297
|
+
if domain_class.is_based_on?
|
298
|
+
nameValuePairs[domain_class.sql_primary_key_name] = 'LAST_INSERT_ID()'
|
298
299
|
end
|
299
300
|
fieldNameStr = nameValuePairs.keys.join ", "
|
300
301
|
fieldValueStr = nameValuePairs.values.join ", "
|
301
|
-
"insert into #{
|
302
|
+
"insert into #{ domain_class.table_name}(#{fieldNameStr}) " +
|
302
303
|
"values(#{fieldValueStr})"
|
303
304
|
end
|
304
305
|
|
@@ -307,35 +308,35 @@ module Lafcadio
|
|
307
308
|
if @obj.error_messages.size > 0
|
308
309
|
raise DomainObjectInitError, @obj.error_messages, caller
|
309
310
|
end
|
310
|
-
@obj.class.self_and_concrete_superclasses.each { |
|
311
|
-
statements << statement_bind_value_pair(
|
311
|
+
@obj.class.self_and_concrete_superclasses.each { |domain_class|
|
312
|
+
statements << statement_bind_value_pair( domain_class )
|
312
313
|
}
|
313
314
|
statements.reverse
|
314
315
|
end
|
315
316
|
|
316
|
-
def statement_bind_value_pair(
|
317
|
+
def statement_bind_value_pair( domain_class )
|
317
318
|
@bind_values = []
|
318
319
|
if @obj.pk_id == nil
|
319
|
-
statement = insert_sql(
|
320
|
+
statement = insert_sql( domain_class )
|
320
321
|
else
|
321
322
|
if @obj.delete
|
322
|
-
statement = delete_sql(
|
323
|
+
statement = delete_sql( domain_class )
|
323
324
|
else
|
324
|
-
statement = update_sql(
|
325
|
+
statement = update_sql( domain_class)
|
325
326
|
end
|
326
327
|
end
|
327
328
|
[statement, @bind_values]
|
328
329
|
end
|
329
330
|
|
330
|
-
def update_sql(
|
331
|
+
def update_sql( domain_class )
|
331
332
|
nameValueStrings = []
|
332
|
-
nameValuePairs = get_name_value_pairs(
|
333
|
+
nameValuePairs = get_name_value_pairs( domain_class )
|
333
334
|
nameValuePairs.each { |key, value|
|
334
335
|
nameValueStrings << "#{key}=#{ value }"
|
335
336
|
}
|
336
337
|
allNameValues = nameValueStrings.join ', '
|
337
|
-
"update #{
|
338
|
-
"where #{
|
338
|
+
"update #{ domain_class.table_name} set #{allNameValues} " +
|
339
|
+
"where #{ domain_class.sql_primary_key_name}=#{@obj.pk_id}"
|
339
340
|
end
|
340
341
|
end
|
341
342
|
|
@@ -427,54 +428,51 @@ module Lafcadio
|
|
427
428
|
end
|
428
429
|
|
429
430
|
# Returns the domain object corresponding to the domain class and pk_id.
|
430
|
-
def get(
|
431
|
-
query = Query.new
|
431
|
+
def get( domain_class, pk_id )
|
432
|
+
query = Query.new domain_class, pk_id
|
432
433
|
@cache.get_by_query( query )[0] ||
|
433
434
|
( raise( DomainObjectNotFoundError,
|
434
|
-
"Can't find #{
|
435
|
+
"Can't find #{domain_class} #{pk_id}", caller ) )
|
435
436
|
end
|
436
437
|
|
437
438
|
# Returns all domain objects for the given domain class.
|
438
|
-
def get_all(
|
439
|
+
def get_all(domain_class); @cache.get_by_query( Query.new( domain_class ) ); end
|
439
440
|
|
440
441
|
# Returns the DbBridge; this is useful in case you need to use raw SQL for a
|
441
442
|
# specific query.
|
442
443
|
def get_db_bridge; @dbBridge; end
|
443
444
|
|
444
445
|
def get_field_name( domain_object )
|
445
|
-
domain_object.
|
446
|
+
domain_object.domain_class.basename.decapitalize
|
446
447
|
end
|
447
448
|
|
448
|
-
def get_filtered(
|
449
|
-
|
449
|
+
def get_filtered(domain_class_name, searchTerm, fieldName = nil) #:nodoc:
|
450
|
+
domain_class = DomainObject.get_domain_class_from_string(
|
451
|
+
domain_class_name
|
452
|
+
)
|
450
453
|
fieldName = get_field_name( searchTerm ) unless fieldName
|
451
|
-
|
452
|
-
cond_class = Query::Link
|
453
|
-
else
|
454
|
-
cond_class = Query::Equals
|
455
|
-
end
|
456
|
-
get_subset( cond_class.new( fieldName, searchTerm, object_type ) )
|
454
|
+
get_subset( Query::Equals.new( fieldName, searchTerm, domain_class ) )
|
457
455
|
end
|
458
456
|
|
459
|
-
def get_map_match(
|
460
|
-
Query::Equals.new( get_field_name( mapped ), mapped,
|
457
|
+
def get_map_match( domain_class, mapped ) #:nodoc:
|
458
|
+
Query::Equals.new( get_field_name( mapped ), mapped, domain_class )
|
461
459
|
end
|
462
460
|
|
463
|
-
def get_map_object(
|
461
|
+
def get_map_object( domain_class, map1, map2 ) #:nodoc:
|
464
462
|
unless map1 && map2
|
465
463
|
raise ArgumentError,
|
466
464
|
"ObjectStore#get_map_object needs two non-nil keys", caller
|
467
465
|
end
|
468
|
-
mapMatch1 = get_map_match
|
469
|
-
mapMatch2 = get_map_match
|
466
|
+
mapMatch1 = get_map_match domain_class, map1
|
467
|
+
mapMatch2 = get_map_match domain_class, map2
|
470
468
|
condition = Query::CompoundCondition.new mapMatch1, mapMatch2
|
471
469
|
get_subset(condition)[0]
|
472
470
|
end
|
473
471
|
|
474
472
|
def get_mapped(searchTerm, resultTypeName) #:nodoc:
|
475
|
-
resultType = DomainObject.
|
476
|
-
firstTypeName = searchTerm.class.
|
477
|
-
secondTypeName = resultType.
|
473
|
+
resultType = DomainObject.get_domain_class_from_string resultTypeName
|
474
|
+
firstTypeName = searchTerm.class.basename
|
475
|
+
secondTypeName = resultType.basename
|
478
476
|
mapTypeName = firstTypeName + secondTypeName
|
479
477
|
get_filtered( mapTypeName, searchTerm ).collect { |mapObj|
|
480
478
|
mapObj.send( resultType.name.decapitalize )
|
@@ -492,14 +490,23 @@ module Lafcadio
|
|
492
490
|
|
493
491
|
# Retrieves a collection of domain objects by +pk_id+.
|
494
492
|
# ObjectStore#get_objects( Clients, [ 1, 2, 3 ] )
|
495
|
-
def get_objects(
|
496
|
-
|
493
|
+
def get_objects( domain_class, pk_ids )
|
494
|
+
if pk_ids.is_a?( Array ) && pk_ids.all? { |elt| elt.is_a?( Integer ) }
|
495
|
+
get_subset Query::In.new( 'pk_id', pk_ids, domain_class )
|
496
|
+
else
|
497
|
+
raise(
|
498
|
+
ArgumentError,
|
499
|
+
"ObjectStore#get_objects( domain_class, pk_ids ): pk_ids needs to " +
|
500
|
+
"be an array of integers",
|
501
|
+
caller
|
502
|
+
)
|
503
|
+
end
|
497
504
|
end
|
498
505
|
|
499
506
|
def get_subset(conditionOrQuery) #:nodoc:
|
500
507
|
if conditionOrQuery.class <= Query::Condition
|
501
508
|
condition = conditionOrQuery
|
502
|
-
query = Query.new condition.
|
509
|
+
query = Query.new condition.domain_class, condition
|
503
510
|
else
|
504
511
|
query = conditionOrQuery
|
505
512
|
end
|
@@ -540,26 +547,28 @@ module Lafcadio
|
|
540
547
|
|
541
548
|
# Flushes a domain object.
|
542
549
|
def flush(db_object)
|
543
|
-
|
544
|
-
flush_collection_cache( db_object.
|
550
|
+
hash_by_domain_class( db_object.domain_class ).delete db_object.pk_id
|
551
|
+
flush_collection_cache( db_object.domain_class )
|
545
552
|
end
|
546
553
|
|
547
|
-
def flush_collection_cache(
|
554
|
+
def flush_collection_cache( domain_class )
|
548
555
|
@collections_by_query.keys.each { |query|
|
549
|
-
if query.
|
556
|
+
if query.domain_class == domain_class
|
550
557
|
@collections_by_query.delete( query )
|
551
558
|
end
|
552
559
|
}
|
553
560
|
end
|
554
561
|
|
555
562
|
# Returns a cached domain object, or nil if none is found.
|
556
|
-
def get(
|
557
|
-
|
563
|
+
def get( domain_class, pk_id )
|
564
|
+
hash_by_domain_class( domain_class )[pk_id].clone
|
558
565
|
end
|
559
566
|
|
560
567
|
# Returns an array of all domain objects of a given type.
|
561
|
-
def get_all(
|
562
|
-
|
568
|
+
def get_all( domain_class )
|
569
|
+
hash_by_domain_class( domain_class ).values.collect { |d_obj|
|
570
|
+
d_obj.clone
|
571
|
+
}
|
563
572
|
end
|
564
573
|
|
565
574
|
def get_by_query( query )
|
@@ -572,17 +581,17 @@ module Lafcadio
|
|
572
581
|
end
|
573
582
|
collection = []
|
574
583
|
@collections_by_query[query].each { |pk_id|
|
575
|
-
dobj = get( query.
|
584
|
+
dobj = get( query.domain_class, pk_id )
|
576
585
|
collection << dobj if dobj
|
577
586
|
}
|
578
587
|
collection
|
579
588
|
end
|
580
589
|
|
581
|
-
def
|
582
|
-
unless @objects[
|
583
|
-
@objects[
|
590
|
+
def hash_by_domain_class( domain_class )
|
591
|
+
unless @objects[domain_class]
|
592
|
+
@objects[domain_class] = {}
|
584
593
|
end
|
585
|
-
@objects[
|
594
|
+
@objects[domain_class]
|
586
595
|
end
|
587
596
|
|
588
597
|
def last_commit_time( domain_class, pk_id )
|
@@ -591,18 +600,19 @@ module Lafcadio
|
|
591
600
|
end
|
592
601
|
|
593
602
|
def set_commit_time( d_obj )
|
594
|
-
by_domain_class = @commit_times[d_obj.
|
603
|
+
by_domain_class = @commit_times[d_obj.domain_class]
|
595
604
|
if by_domain_class.nil?
|
596
605
|
by_domain_class = {}
|
597
|
-
@commit_times[d_obj.
|
606
|
+
@commit_times[d_obj.domain_class] = by_domain_class
|
598
607
|
end
|
599
608
|
by_domain_class[d_obj.pk_id] = Time.now
|
600
609
|
end
|
601
610
|
|
602
611
|
# Saves a domain object.
|
603
612
|
def save(db_object)
|
604
|
-
|
605
|
-
|
613
|
+
hash = hash_by_domain_class( db_object.domain_class )
|
614
|
+
hash[db_object.pk_id] = db_object
|
615
|
+
flush_collection_cache( db_object.domain_class )
|
606
616
|
end
|
607
617
|
|
608
618
|
def update_after_commit( committer ) #:nodoc:
|
@@ -675,29 +685,30 @@ module Lafcadio
|
|
675
685
|
def dispatch_get_method
|
676
686
|
begin
|
677
687
|
dispatch_get_singular
|
678
|
-
rescue
|
679
|
-
|
680
|
-
|
688
|
+
rescue CouldntMatchDomainClassError
|
689
|
+
domain_class_name = English.singular(
|
690
|
+
camel_case_method_name_after_get
|
691
|
+
)
|
681
692
|
begin
|
682
|
-
@domain_class =
|
683
|
-
|
693
|
+
@domain_class =
|
694
|
+
DomainObject.get_domain_class_from_string( domain_class_name )
|
684
695
|
dispatch_get_plural
|
685
|
-
rescue
|
696
|
+
rescue CouldntMatchDomainClassError
|
686
697
|
raise_no_method_error
|
687
698
|
end
|
688
699
|
end
|
689
700
|
end
|
690
701
|
|
691
702
|
def dispatch_get_singular
|
692
|
-
|
703
|
+
domain_class = DomainObject.get_domain_class_from_string(
|
693
704
|
camel_case_method_name_after_get
|
694
705
|
)
|
695
706
|
if @orig_args[0].class <= Integer
|
696
707
|
@symbol = :get
|
697
|
-
@args = [
|
708
|
+
@args = [ domain_class, @orig_args[0] ]
|
698
709
|
elsif @orig_args[0].class <= DomainObject
|
699
710
|
@symbol = :get_map_object
|
700
|
-
@args = [
|
711
|
+
@args = [ domain_class, @orig_args[0], @orig_args[1] ]
|
701
712
|
end
|
702
713
|
end
|
703
714
|
|
@@ -713,16 +724,16 @@ module Lafcadio
|
|
713
724
|
end
|
714
725
|
|
715
726
|
class SqlValueConverter #:nodoc:
|
716
|
-
attr_reader :
|
727
|
+
attr_reader :domain_class, :row_hash
|
717
728
|
|
718
|
-
def initialize(
|
719
|
-
@
|
729
|
+
def initialize( domain_class, row_hash )
|
730
|
+
@domain_class = domain_class
|
720
731
|
@row_hash = row_hash
|
721
732
|
end
|
722
733
|
|
723
734
|
def []( key )
|
724
735
|
begin
|
725
|
-
field = @
|
736
|
+
field = @domain_class.get_field( key )
|
726
737
|
val = field.value_from_sql( @row_hash[ field.db_field_name ] )
|
727
738
|
if field.instance_of?( PrimaryKeyField ) && val.nil?
|
728
739
|
raise FieldMatchError, error_msg, caller
|
@@ -735,9 +746,9 @@ module Lafcadio
|
|
735
746
|
end
|
736
747
|
|
737
748
|
def error_msg
|
738
|
-
"The field \"" + @
|
749
|
+
"The field \"" + @domain_class.sql_primary_key_name +
|
739
750
|
"\" can\'t be found in the table \"" +
|
740
|
-
@
|
751
|
+
@domain_class.table_name + "\"."
|
741
752
|
end
|
742
753
|
end
|
743
754
|
end
|