lafcadio 0.5.2 → 0.6.0
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/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
|