lafcadio 0.8.3 → 0.9.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/lib/lafcadio.rb +1 -1
- data/lib/lafcadio.rb~ +1 -1
- data/lib/lafcadio/dateTime.rb~ +93 -0
- data/lib/lafcadio/depend.rb~ +8 -0
- data/lib/lafcadio/domain.rb +127 -120
- data/lib/lafcadio/domain.rb~ +48 -40
- data/lib/lafcadio/mock.rb +9 -12
- data/lib/lafcadio/mock.rb~ +110 -0
- data/lib/lafcadio/objectField.rb +6 -6
- data/lib/lafcadio/objectField.rb~ +564 -0
- data/lib/lafcadio/objectStore.rb +45 -24
- data/lib/lafcadio/objectStore.rb.~1.64.~ +766 -0
- data/lib/lafcadio/objectStore.rb~ +57 -26
- data/lib/lafcadio/query.rb +57 -22
- data/lib/lafcadio/query.rb~ +48 -17
- data/lib/lafcadio/schema.rb~ +56 -0
- data/lib/lafcadio/test.rb +218 -0
- data/lib/lafcadio/test.rb~ +25 -0
- data/lib/lafcadio/test/testconfig.dat~ +13 -0
- data/lib/lafcadio/util.rb +3 -2
- data/lib/lafcadio/util.rb~ +104 -0
- metadata +111 -97
data/lib/lafcadio.rb
CHANGED
data/lib/lafcadio.rb~
CHANGED
@@ -0,0 +1,93 @@
|
|
1
|
+
module Lafcadio
|
2
|
+
# Represents a specific month in time. With the exception of
|
3
|
+
# Month.month_names (which returns a zero-based array), every usage of the
|
4
|
+
# month value assumes that 1 equals January and 12 equals December.
|
5
|
+
class Month
|
6
|
+
# Returns an array of the full names of months (in English). Note that
|
7
|
+
# "January" is the 0th element, and "December" is the 11th element.
|
8
|
+
def Month.month_names
|
9
|
+
[ "January", "February", "March", "April", "May", "June", "July",
|
10
|
+
"August", "September", "October", "November", "December" ]
|
11
|
+
end
|
12
|
+
|
13
|
+
include Comparable
|
14
|
+
|
15
|
+
attr_reader :month, :year
|
16
|
+
|
17
|
+
# A new month can be set to a specific +month+ and +year+, or you can call
|
18
|
+
# Month.new with no arguments to receive the current month.
|
19
|
+
def initialize( year = nil, month = nil )
|
20
|
+
require 'date'
|
21
|
+
if month.nil? || year.nil?
|
22
|
+
date = Date.today
|
23
|
+
month = date.mon unless month
|
24
|
+
year = date.year unless year
|
25
|
+
end
|
26
|
+
fail "invalid month" if month < 1 || month > 12
|
27
|
+
@month = month
|
28
|
+
@year = year
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns a new Month that is +amountToAdd+ months later.
|
32
|
+
def +( amountToAdd )
|
33
|
+
( fullYears, remainingMonths ) = amountToAdd.divmod( 12 )
|
34
|
+
resultYear = @year + fullYears
|
35
|
+
resultMonth = @month + remainingMonths
|
36
|
+
if resultMonth > 12
|
37
|
+
resultMonth -= 12
|
38
|
+
resultYear += 1
|
39
|
+
end
|
40
|
+
Month.new( resultYear, resultMonth )
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns a new Month that is +amountToSubtract+ months earlier.
|
44
|
+
def -(amountToSubtract)
|
45
|
+
self + (-amountToSubtract)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Compare this Month to another Month.
|
49
|
+
def <=>(anOther)
|
50
|
+
if @year == anOther.year
|
51
|
+
@month <=> anOther.month
|
52
|
+
else
|
53
|
+
@year <=> anOther.year
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the last Date of the month.
|
58
|
+
def end_date
|
59
|
+
self.next.start_date - 1
|
60
|
+
end
|
61
|
+
|
62
|
+
# Is this Month equal to +anOther+? +anOther+ must be another Month of the
|
63
|
+
# same value.
|
64
|
+
def eql?(anOther)
|
65
|
+
self == anOther
|
66
|
+
end
|
67
|
+
|
68
|
+
# Calculate a hash value for this Month.
|
69
|
+
def hash
|
70
|
+
"#{@year}#{@month}".to_i
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns the next Month.
|
74
|
+
def next
|
75
|
+
self + 1
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the previous Month.
|
79
|
+
def prev
|
80
|
+
self - 1
|
81
|
+
end
|
82
|
+
|
83
|
+
# Returns the first Date of the month.
|
84
|
+
def start_date
|
85
|
+
Date.new( @year, @month, 1 )
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns a string of the format "January 2001".
|
89
|
+
def to_s
|
90
|
+
Month.month_names[@month-1][0..2] + " " + @year.to_s
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/lafcadio/domain.rb
CHANGED
@@ -137,9 +137,7 @@ module Lafcadio
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
def eql?(otherObj)
|
141
|
-
self == otherObj
|
142
|
-
end
|
140
|
+
def eql?( otherObj ); self == otherObj; end
|
143
141
|
|
144
142
|
def hash; "#{ self.class.name } #{ pk_id }".hash; end
|
145
143
|
end
|
@@ -242,18 +240,7 @@ module Lafcadio
|
|
242
240
|
# that each table has a +pk_id+ field that is used to match rows between
|
243
241
|
# different levels.
|
244
242
|
class DomainObject
|
245
|
-
@@
|
246
|
-
@@class_fields = {}
|
247
|
-
@@pk_fields =
|
248
|
-
Hash.new { |hash, key|
|
249
|
-
pk_field = PrimaryKeyField.new( key )
|
250
|
-
pk_field.db_field_name = @@sql_primary_keys[key]
|
251
|
-
hash[key] = pk_field
|
252
|
-
}
|
253
|
-
@@sql_primary_keys = Hash.new( 'pk_id' )
|
254
|
-
@@default_field_setup_hashes = Hash.new { |hash, key|
|
255
|
-
hash[key] = Hash.new( {} )
|
256
|
-
}
|
243
|
+
@@subclass_records = Hash.new do |h, k| h[k] = SubclassRecord.new( k ); end
|
257
244
|
|
258
245
|
COMMIT_ADD = 1
|
259
246
|
COMMIT_EDIT = 2
|
@@ -264,7 +251,6 @@ module Lafcadio
|
|
264
251
|
def self.[]( pk_id ); get( pk_id ); end
|
265
252
|
|
266
253
|
def self.abstract_subclasses #:nodoc:
|
267
|
-
require 'lafcadio/domain'
|
268
254
|
[ MapObject ]
|
269
255
|
end
|
270
256
|
|
@@ -273,19 +259,23 @@ module Lafcadio
|
|
273
259
|
# Returns an array of all fields defined for this class and all concrete
|
274
260
|
# superclasses.
|
275
261
|
def self.all_fields
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
}
|
280
|
-
all_fields
|
262
|
+
self_and_concrete_superclasses.map { |a_class|
|
263
|
+
a_class.class_fields
|
264
|
+
}.flatten
|
281
265
|
end
|
282
266
|
|
267
|
+
def self.class_field(fieldName) #:nodoc:
|
268
|
+
field = nil
|
269
|
+
self.class_fields.each { |aField|
|
270
|
+
field = aField if aField.name == fieldName
|
271
|
+
}
|
272
|
+
field
|
273
|
+
end
|
274
|
+
|
283
275
|
def self.class_fields #:nodoc:
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
class_fields = @@class_fields[self]
|
288
|
-
class_fields.each do |class_field|
|
276
|
+
unless subclass_record.fields
|
277
|
+
subclass_record.fields = self.get_class_fields
|
278
|
+
subclass_record.fields.each do |class_field|
|
289
279
|
begin
|
290
280
|
undef_method class_field.name.to_sym
|
291
281
|
rescue NameError
|
@@ -293,52 +283,50 @@ module Lafcadio
|
|
293
283
|
end
|
294
284
|
end
|
295
285
|
end
|
296
|
-
|
286
|
+
subclass_record.fields
|
297
287
|
end
|
298
288
|
|
299
289
|
def self.create_field( field_class, *args )
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
att_hash
|
290
|
+
subclass_record.maybe_init_fields
|
291
|
+
att_hash = create_field_att_hash( field_class, *args )
|
292
|
+
field = field_class.create_with_args( self, att_hash )
|
293
|
+
unless class_fields.any? { |cf| cf.name == field.name }
|
294
|
+
att_hash.each { |field_name, value|
|
295
|
+
setter = field_name + '='
|
296
|
+
field.send( setter, value ) if field.respond_to?( setter )
|
297
|
+
}
|
298
|
+
class_fields << field
|
305
299
|
end
|
306
|
-
|
307
|
-
|
308
|
-
|
300
|
+
end
|
301
|
+
|
302
|
+
def self.create_field_att_hash( field_class, *args ) #:nodoc:
|
303
|
+
att_hash = args.last
|
304
|
+
unless att_hash.is_a? Hash
|
305
|
+
att_hash = subclass_record.default_field_setup_hash[
|
306
|
+
field_class
|
307
|
+
].clone
|
309
308
|
end
|
310
309
|
if field_class == DomainObjectField
|
311
310
|
att_hash['linked_type'] = args.first
|
312
311
|
att_hash['name'] = args[1] if args[1] and !args[1].is_a? Hash
|
313
312
|
else
|
314
313
|
name = args.first
|
315
|
-
att_hash['name'] = name
|
316
|
-
end
|
317
|
-
field = field_class.instantiate_with_parameters( self, att_hash )
|
318
|
-
unless class_fields.any? { |cf| cf.name == field.name }
|
319
|
-
att_hash.each { |field_name, value|
|
320
|
-
setter = field_name + '='
|
321
|
-
field.send( setter, value ) if field.respond_to?( setter )
|
322
|
-
}
|
323
|
-
class_fields << field
|
314
|
+
att_hash['name'] = name.is_a?( String ) ? name : name.to_s
|
324
315
|
end
|
316
|
+
att_hash
|
325
317
|
end
|
326
318
|
|
327
319
|
def self.default_field_setup_hash( field_class, hash )
|
328
|
-
|
320
|
+
subclass_record.default_field_setup_hash[field_class] = hash
|
329
321
|
end
|
330
322
|
|
331
323
|
def self.dependent_classes #:nodoc:
|
332
324
|
dependent_classes = {}
|
333
325
|
DomainObject.subclasses.each { |aClass|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
field.linked_type == self.domain_class )
|
339
|
-
dependent_classes[aClass] = field
|
340
|
-
end
|
341
|
-
}
|
326
|
+
unless DomainObject.abstract_subclasses.include?( aClass )
|
327
|
+
if ( field = aClass.get_link_field( self ) )
|
328
|
+
dependent_classes[aClass] = field
|
329
|
+
end
|
342
330
|
end
|
343
331
|
}
|
344
332
|
dependent_classes
|
@@ -352,30 +340,35 @@ module Lafcadio
|
|
352
340
|
end
|
353
341
|
|
354
342
|
def self.first; all.first; end
|
355
|
-
|
356
|
-
def self.
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
343
|
+
|
344
|
+
def self.get( *args )
|
345
|
+
if block_given?
|
346
|
+
query = Query.infer( self ) { |dobj| yield( dobj ) }
|
347
|
+
ObjectStore.get_object_store.get_subset( query )
|
348
|
+
elsif args.size == 1
|
349
|
+
arg = args.first
|
350
|
+
if arg.is_a? Fixnum
|
351
|
+
ObjectStore.get_object_store.get( self, *args )
|
352
|
+
else
|
353
|
+
qry = Query.new( self, nil, { :group_functions => [ :count ] } )
|
354
|
+
ObjectStore.get_object_store.query qry
|
355
|
+
end
|
356
|
+
else
|
357
|
+
ObjectStore.get_object_store.get_filtered( self.name, *args )
|
358
|
+
end
|
366
359
|
end
|
367
360
|
|
368
361
|
# Returns an Array of ObjectField instances for this domain class, parsing
|
369
362
|
# them from XML if necessary.
|
370
363
|
def self.get_class_fields
|
371
364
|
if self.methods( false ).include?( 'get_class_fields' )
|
372
|
-
[
|
365
|
+
[ subclass_record.pk_field ]
|
373
366
|
elsif abstract_subclasses.include?( self )
|
374
367
|
[]
|
375
368
|
else
|
376
369
|
xmlParser = try_load_xml_parser
|
377
370
|
if xmlParser
|
378
|
-
xmlParser.get_class_fields
|
371
|
+
xmlParser.get_class_fields
|
379
372
|
else
|
380
373
|
error_msg = "Couldn't find either an XML class description file " +
|
381
374
|
"or get_class_fields method for " + self.name
|
@@ -396,7 +389,7 @@ module Lafcadio
|
|
396
389
|
aDomainClass = self
|
397
390
|
field = nil
|
398
391
|
while aDomainClass < DomainObject && !field
|
399
|
-
field = aDomainClass.
|
392
|
+
field = aDomainClass.class_field( fieldName )
|
400
393
|
aDomainClass = aDomainClass.superclass
|
401
394
|
end
|
402
395
|
if field
|
@@ -429,7 +422,7 @@ module Lafcadio
|
|
429
422
|
end
|
430
423
|
|
431
424
|
def self.inherited(subclass) #:nodoc:
|
432
|
-
@@
|
425
|
+
@@subclass_records[subclass]
|
433
426
|
end
|
434
427
|
|
435
428
|
def self.is_based_on? #:nodoc:
|
@@ -444,44 +437,33 @@ module Lafcadio
|
|
444
437
|
|
445
438
|
def self.method_missing( methodId, *args ) #:nodoc:
|
446
439
|
method_name = methodId.id2name
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
field_class = Lafcadio.const_get( maybe_field_class_name )
|
467
|
-
arg = args.shift
|
468
|
-
until args.empty?
|
469
|
-
next_arg = args.shift
|
470
|
-
if next_arg.is_a? String or next_arg.is_a? Symbol
|
471
|
-
create_field( field_class, arg )
|
472
|
-
arg = next_arg
|
473
|
-
else
|
474
|
-
create_field( field_class, arg, next_arg )
|
475
|
-
arg = args.shift
|
476
|
-
end
|
440
|
+
maybe_field_class_name = method_name.underscore_to_camel_case + 'Field'
|
441
|
+
begin
|
442
|
+
field_class = Lafcadio.const_get( maybe_field_class_name )
|
443
|
+
create_field( field_class, *args )
|
444
|
+
rescue NameError
|
445
|
+
singular = method_name.singular
|
446
|
+
if singular
|
447
|
+
maybe_field_class_name = singular.underscore_to_camel_case + 'Field'
|
448
|
+
begin
|
449
|
+
field_class = Lafcadio.const_get( maybe_field_class_name )
|
450
|
+
arg = args.shift
|
451
|
+
until args.empty?
|
452
|
+
next_arg = args.shift
|
453
|
+
if next_arg.is_a? String or next_arg.is_a? Symbol
|
454
|
+
create_field( field_class, arg )
|
455
|
+
arg = next_arg
|
456
|
+
else
|
457
|
+
create_field( field_class, arg, next_arg )
|
458
|
+
arg = args.shift
|
477
459
|
end
|
478
|
-
create_field( field_class, arg ) unless arg.nil?
|
479
|
-
rescue NameError
|
480
|
-
super
|
481
460
|
end
|
482
|
-
|
461
|
+
create_field( field_class, arg ) unless arg.nil?
|
462
|
+
rescue NameError
|
483
463
|
super
|
484
464
|
end
|
465
|
+
else
|
466
|
+
super
|
485
467
|
end
|
486
468
|
end
|
487
469
|
end
|
@@ -522,7 +504,7 @@ module Lafcadio
|
|
522
504
|
begin
|
523
505
|
get_field( 'pk_id' ).db_field_name = self.send( symbol )
|
524
506
|
rescue NameError
|
525
|
-
|
507
|
+
subclass_record.sql_primary_key = self.send( symbol )
|
526
508
|
end
|
527
509
|
end
|
528
510
|
end
|
@@ -535,9 +517,11 @@ module Lafcadio
|
|
535
517
|
end
|
536
518
|
get_field( 'pk_id' ).db_field_name
|
537
519
|
end
|
520
|
+
|
521
|
+
def self.subclass_record; @@subclass_records[self]; end
|
538
522
|
|
539
523
|
def self.subclasses #:nodoc:
|
540
|
-
@@
|
524
|
+
@@subclass_records.keys
|
541
525
|
end
|
542
526
|
|
543
527
|
# Returns the table name, which is assumed to be the domain class name
|
@@ -561,16 +545,15 @@ module Lafcadio
|
|
561
545
|
|
562
546
|
def self.try_load_xml_parser
|
563
547
|
require 'lafcadio/domain'
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
end
|
548
|
+
dirName = LafcadioConfig.new['classDefinitionDir']
|
549
|
+
xmlFileName = self.basename + '.xml'
|
550
|
+
xmlPath = File.join( dirName, xmlFileName )
|
551
|
+
xml = ''
|
552
|
+
begin
|
553
|
+
File.open( xmlPath ) { |file| xml = file.readlines.join }
|
554
|
+
ClassDefinitionXmlParser.new( self, xml )
|
555
|
+
rescue Errno::ENOENT
|
556
|
+
# no xml file, so no @xmlParser
|
574
557
|
end
|
575
558
|
end
|
576
559
|
|
@@ -595,6 +578,7 @@ module Lafcadio
|
|
595
578
|
def initialize(fieldHash)
|
596
579
|
if fieldHash.respond_to? :keys
|
597
580
|
fieldHash.keys.each { |key|
|
581
|
+
key = key.to_s
|
598
582
|
begin
|
599
583
|
self.class.get_field( key )
|
600
584
|
rescue MissingError
|
@@ -602,11 +586,16 @@ module Lafcadio
|
|
602
586
|
end
|
603
587
|
}
|
604
588
|
end
|
605
|
-
|
589
|
+
if fieldHash.is_a? Hash
|
590
|
+
@fieldHash = {}
|
591
|
+
fieldHash.each do |k, v| @fieldHash[k.to_s] = v; end
|
592
|
+
else
|
593
|
+
@fieldHash = fieldHash
|
594
|
+
end
|
606
595
|
@error_messages = []
|
607
596
|
@fields = {}
|
608
597
|
@fields_set = []
|
609
|
-
|
598
|
+
@original_values = OriginalValuesHash.new( @fieldHash )
|
610
599
|
check_fields = LafcadioConfig.new()['checkFields']
|
611
600
|
verify if %w( onInstantiate onAllStates ).include?( check_fields )
|
612
601
|
end
|
@@ -700,10 +689,6 @@ module Lafcadio
|
|
700
689
|
def post_commit_trigger
|
701
690
|
nil
|
702
691
|
end
|
703
|
-
|
704
|
-
def reset_original_values_hash( f = @fields ) #:nodoc:
|
705
|
-
@original_values = OriginalValuesHash.new( f.clone )
|
706
|
-
end
|
707
692
|
|
708
693
|
def set_field( field, value ) #:nodoc:
|
709
694
|
if field.class <= DomainObjectField
|
@@ -735,6 +720,28 @@ module Lafcadio
|
|
735
720
|
class OriginalValuesHash < DelegateClass( Hash )
|
736
721
|
def []=( key, val ); raise NoMethodError; end
|
737
722
|
end
|
723
|
+
|
724
|
+
class SubclassRecord
|
725
|
+
attr_accessor :default_field_setup_hash, :fields, :sql_primary_key
|
726
|
+
|
727
|
+
def initialize( subclass )
|
728
|
+
@subclass = subclass
|
729
|
+
@default_field_setup_hash = Hash.new( {} )
|
730
|
+
@sql_primary_key = 'pk_id'
|
731
|
+
end
|
732
|
+
|
733
|
+
def maybe_init_fields
|
734
|
+
self.fields = [ pk_field ] if self.fields.nil?
|
735
|
+
end
|
736
|
+
|
737
|
+
def pk_field
|
738
|
+
if @pk_field.nil?
|
739
|
+
@pk_field = PrimaryKeyField.new @subclass
|
740
|
+
@pk_field.db_field_name = sql_primary_key
|
741
|
+
end
|
742
|
+
@pk_field
|
743
|
+
end
|
744
|
+
end
|
738
745
|
end
|
739
746
|
|
740
747
|
# Any domain class that is used mostly to map between two other domain
|