lafcadio 0.7.3 → 0.7.4

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.
@@ -16,9 +16,8 @@
16
16
  # http://lafcadio.rubyforge.org/tutorial.html.
17
17
 
18
18
  module Lafcadio
19
- Version = "0.7.3"
19
+ Version = "0.7.4"
20
20
 
21
- require 'lafcadio/dateTime'
22
21
  require 'lafcadio/depend'
23
22
  require 'lafcadio/domain'
24
23
  require 'lafcadio/mock'
@@ -16,9 +16,8 @@
16
16
  # http://lafcadio.rubyforge.org/tutorial.html.
17
17
 
18
18
  module Lafcadio
19
- Version = "0.7.2"
19
+ Version = "0.7.3"
20
20
 
21
- require 'lafcadio/dateTime'
22
21
  require 'lafcadio/depend'
23
22
  require 'lafcadio/domain'
24
23
  require 'lafcadio/mock'
@@ -1,7 +1,7 @@
1
1
  module Lafcadio
2
- # Represents a specific month in time. With the exception of Month.month_names
3
- # (which returns a zero-based array), every usage of the month value assumes
4
- # that 1 equals January and 12 equals December.
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
5
  class Month
6
6
  # Returns an array of the full names of months (in English). Note that
7
7
  # "January" is the 0th element, and "December" is the 11th element.
@@ -1,5 +1,9 @@
1
+ require 'contxtlservice'
1
2
  require 'dbi'
3
+ require 'englishext'
2
4
  require 'extensions/all'
3
5
  require 'extensions/module'
4
6
  require 'log4r'
5
- require 'runit/testcase'
7
+ require 'month'
8
+ require 'queuehash'
9
+ require 'uscommerce'
@@ -0,0 +1,8 @@
1
+ require 'dbi'
2
+ require 'englishext'
3
+ require 'extensions/all'
4
+ require 'extensions/module'
5
+ require 'log4r'
6
+ require 'month'
7
+ require 'queuehash'
8
+ require 'uscommerce'
@@ -98,7 +98,7 @@ module Lafcadio
98
98
 
99
99
  def value_from_elt( elt )
100
100
  hash = {}
101
- elt.elements.each( English.singular( @name ) ) { |subElt|
101
+ elt.elements.each( @name.singular ) { |subElt|
102
102
  key = subElt.attributes['key'] == 'true'
103
103
  value = subElt.text.to_s
104
104
  hash[key] = value
@@ -155,9 +155,9 @@ module Lafcadio
155
155
  # 2. Write one XML file per domain class. For example, a User.xml file
156
156
  # might look like:
157
157
  # <lafcadio_class_definition name="User">
158
- # <field name="lastName" class="TextField"/>
159
- # <field name="email" class="TextField"/>
160
- # <field name="password" class="TextField"/>
158
+ # <field name="lastName" class="StringField"/>
159
+ # <field name="email" class="StringField"/>
160
+ # <field name="password" class="StringField"/>
161
161
  # <field name="birthday" class="DateField"/>
162
162
  # </lafcadio_class_definition>
163
163
  # 2. Overriding DomainObject.get_class_fields. The method should return an Array
@@ -166,10 +166,10 @@ module Lafcadio
166
166
  # class User < DomainObject
167
167
  # def User.get_class_fields
168
168
  # fields = []
169
- # fields << TextField.new(self, 'firstName')
170
- # fields << TextField.new(self, 'lastName')
171
- # fields << TextField.new(self, 'email')
172
- # fields << TextField.new(self, 'password')
169
+ # fields << StringField.new(self, 'firstName')
170
+ # fields << StringField.new(self, 'lastName')
171
+ # fields << StringField.new(self, 'email')
172
+ # fields << StringField.new(self, 'password')
173
173
  # fields << DateField.new(self, 'birthday')
174
174
  # fields
175
175
  # end
@@ -188,13 +188,13 @@ module Lafcadio
188
188
  # john.email = 'john.doe@mail.email.com'
189
189
  #
190
190
  # If your domain class has fields that refer to other domain classes, or even
191
- # to another row in the same table, you can use a LinkField to express the
191
+ # to another row in the same table, you can use a DomainObjectField to express the
192
192
  # relation.
193
193
  # <lafcadio_class_definition name="Message">
194
- # <field name="subject" class="TextField" />
195
- # <field name="body" class="TextField" />
196
- # <field name="author" class="LinkField" linked_type="User" />
197
- # <field name="recipient" class="LinkField" linked_type="User" />
194
+ # <field name="subject" class="StringField" />
195
+ # <field name="body" class="StringField" />
196
+ # <field name="author" class="DomainObjectField" linked_type="User" />
197
+ # <field name="recipient" class="DomainObjectField" linked_type="User" />
198
198
  # <field name="dateSent" class="DateField" />
199
199
  # </lafcadio_class_definition>
200
200
  #
@@ -251,6 +251,9 @@ module Lafcadio
251
251
  hash[key] = pk_field
252
252
  }
253
253
  @@sql_primary_keys = Hash.new( 'pk_id' )
254
+ @@default_field_setup_hashes = Hash.new { |hash, key|
255
+ hash[key] = Hash.new( {} )
256
+ }
254
257
 
255
258
  COMMIT_ADD = 1
256
259
  COMMIT_EDIT = 2
@@ -282,40 +285,56 @@ module Lafcadio
282
285
  unless class_fields
283
286
  @@class_fields[self] = self.get_class_fields
284
287
  class_fields = @@class_fields[self]
288
+ class_fields.each do |class_field|
289
+ begin
290
+ undef_method class_field.name.to_sym
291
+ rescue NameError
292
+ # not defined globally or in an included Module, skip it
293
+ end
294
+ end
285
295
  end
286
296
  class_fields
287
297
  end
288
298
 
289
299
  def self.create_field( field_class, *args )
290
300
  class_fields = @@class_fields[self]
301
+ if args.last.is_a? Hash
302
+ att_hash = args.last
303
+ else
304
+ att_hash = @@default_field_setup_hashes[self][field_class].clone
305
+ end
291
306
  if class_fields.nil?
292
307
  class_fields = [ @@pk_fields[self] ]
293
308
  @@class_fields[self] = class_fields
294
309
  end
295
- if field_class == LinkField
296
- att_hash = args.last.is_a?( Hash ) ? args.last : {}
310
+ if field_class == DomainObjectField
297
311
  att_hash['linked_type'] = args.first
298
312
  att_hash['name'] = args[1] if args[1] and !args[1].is_a? Hash
299
313
  else
300
- att_hash = args[1] || {}
301
314
  name = args.first
302
315
  att_hash['name'] = name == String ? name : name.to_s
303
316
  end
304
317
  field = field_class.instantiate_with_parameters( self, att_hash )
305
- att_hash.each { |field_name, value|
306
- setter = field_name + '='
307
- field.send( setter, value ) if field.respond_to?( setter )
308
- }
309
- class_fields << field
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
324
+ end
310
325
  end
311
326
 
327
+ def self.default_field_setup_hash( field_class, hash )
328
+ @@default_field_setup_hashes[self][field_class] = hash
329
+ end
330
+
312
331
  def self.dependent_classes #:nodoc:
313
332
  dependent_classes = {}
314
333
  DomainObject.subclasses.each { |aClass|
315
334
  if aClass != DomainObjectProxy &&
316
335
  (!DomainObject.abstract_subclasses.index(aClass))
317
336
  aClass.class_fields.each { |field|
318
- if ( field.is_a?( LinkField ) &&
337
+ if ( field.is_a?( DomainObjectField ) &&
319
338
  field.linked_type == self.domain_class )
320
339
  dependent_classes[aClass] = field
321
340
  end
@@ -325,6 +344,13 @@ module Lafcadio
325
344
  dependent_classes
326
345
  end
327
346
 
347
+ def self.exist?( search_term, field_name = :pk_id )
348
+ query = Query.infer( self ) { |dobj|
349
+ dobj.send( field_name ).equals( search_term )
350
+ }
351
+ !ObjectStore.get_object_store.get_subset( query ).empty?
352
+ end
353
+
328
354
  def self.first; all.first; end
329
355
 
330
356
  def self.get_class_field(fieldName) #:nodoc:
@@ -398,7 +424,7 @@ module Lafcadio
398
424
 
399
425
  def self.get_link_field( linked_domain_class ) # :nodoc:
400
426
  class_fields.find { |field|
401
- field.is_a? LinkField and field.linked_type == linked_domain_class
427
+ field.is_a? DomainObjectField and field.linked_type == linked_domain_class
402
428
  }
403
429
  end
404
430
 
@@ -422,8 +448,10 @@ module Lafcadio
422
448
  if block_given?
423
449
  query = Query.infer( self ) { |dobj| yield( dobj ) }
424
450
  ObjectStore.get_object_store.get_subset( query )
425
- else
451
+ elsif args.size == 1
426
452
  ObjectStore.get_object_store.get( self, *args )
453
+ else
454
+ ObjectStore.get_object_store.get_filtered( self.name, *args )
427
455
  end
428
456
  else
429
457
  maybe_field_class_name = method_name.underscore_to_camel_case + 'Field'
@@ -431,7 +459,29 @@ module Lafcadio
431
459
  field_class = Lafcadio.const_get( maybe_field_class_name )
432
460
  create_field( field_class, *args )
433
461
  rescue NameError
434
- super
462
+ singular = method_name.singular
463
+ if singular
464
+ maybe_field_class_name = singular.underscore_to_camel_case + 'Field'
465
+ begin
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
477
+ end
478
+ create_field( field_class, arg ) unless arg.nil?
479
+ rescue NameError
480
+ super
481
+ end
482
+ else
483
+ super
484
+ end
435
485
  end
436
486
  end
437
487
  end
@@ -504,7 +554,7 @@ module Lafcadio
504
554
  if (!xmlParser.nil? && table_name = xmlParser.table_name)
505
555
  table_name
506
556
  else
507
- English.plural( self.basename.camel_case_to_underscore )
557
+ self.basename.camel_case_to_underscore.plural
508
558
  end
509
559
  end
510
560
  end
@@ -555,6 +605,7 @@ module Lafcadio
555
605
  @error_messages = []
556
606
  @fields = {}
557
607
  @fields_set = []
608
+ @original_values = OriginalValuesHash.new( @fieldHash )
558
609
  check_fields = LafcadioConfig.new()['checkFields']
559
610
  verify if %w( onInstantiate onAllStates ).include?( check_fields )
560
611
  end
@@ -580,6 +631,11 @@ module Lafcadio
580
631
  end
581
632
  @delete = value
582
633
  end
634
+
635
+ def delete!
636
+ self.delete = true
637
+ commit
638
+ end
583
639
 
584
640
  def get_field( field ) #:nodoc:
585
641
  unless @fields_set.include?( field )
@@ -645,7 +701,7 @@ module Lafcadio
645
701
  end
646
702
 
647
703
  def set_field( field, value ) #:nodoc:
648
- if field.class <= LinkField
704
+ if field.class <= DomainObjectField
649
705
  if value.class != DomainObjectProxy && value
650
706
  value = DomainObjectProxy.new(value)
651
707
  end
@@ -658,6 +714,11 @@ module Lafcadio
658
714
  @fields_set << field
659
715
  end
660
716
 
717
+ def update!( changes )
718
+ changes.each do |sym, value| self.send( sym.to_s + '=', value ); end
719
+ commit
720
+ end
721
+
661
722
  def verify
662
723
  if ObjectStore.get_object_store.mock?
663
724
  self.class.get_class_fields.each { |field|
@@ -665,6 +726,10 @@ module Lafcadio
665
726
  }
666
727
  end
667
728
  end
729
+
730
+ class OriginalValuesHash < DelegateClass( Hash )
731
+ def []=( key, val ); raise NoMethodError; end
732
+ end
668
733
  end
669
734
 
670
735
  # Any domain class that is used mostly to map between two other domain
@@ -98,7 +98,7 @@ module Lafcadio
98
98
 
99
99
  def value_from_elt( elt )
100
100
  hash = {}
101
- elt.elements.each( English.singular( @name ) ) { |subElt|
101
+ elt.elements.each( @name.singular ) { |subElt|
102
102
  key = subElt.attributes['key'] == 'true'
103
103
  value = subElt.text.to_s
104
104
  hash[key] = value
@@ -155,9 +155,9 @@ module Lafcadio
155
155
  # 2. Write one XML file per domain class. For example, a User.xml file
156
156
  # might look like:
157
157
  # <lafcadio_class_definition name="User">
158
- # <field name="lastName" class="TextField"/>
159
- # <field name="email" class="TextField"/>
160
- # <field name="password" class="TextField"/>
158
+ # <field name="lastName" class="StringField"/>
159
+ # <field name="email" class="StringField"/>
160
+ # <field name="password" class="StringField"/>
161
161
  # <field name="birthday" class="DateField"/>
162
162
  # </lafcadio_class_definition>
163
163
  # 2. Overriding DomainObject.get_class_fields. The method should return an Array
@@ -166,10 +166,10 @@ module Lafcadio
166
166
  # class User < DomainObject
167
167
  # def User.get_class_fields
168
168
  # fields = []
169
- # fields << TextField.new(self, 'firstName')
170
- # fields << TextField.new(self, 'lastName')
171
- # fields << TextField.new(self, 'email')
172
- # fields << TextField.new(self, 'password')
169
+ # fields << StringField.new(self, 'firstName')
170
+ # fields << StringField.new(self, 'lastName')
171
+ # fields << StringField.new(self, 'email')
172
+ # fields << StringField.new(self, 'password')
173
173
  # fields << DateField.new(self, 'birthday')
174
174
  # fields
175
175
  # end
@@ -188,13 +188,13 @@ module Lafcadio
188
188
  # john.email = 'john.doe@mail.email.com'
189
189
  #
190
190
  # If your domain class has fields that refer to other domain classes, or even
191
- # to another row in the same table, you can use a LinkField to express the
191
+ # to another row in the same table, you can use a DomainObjectField to express the
192
192
  # relation.
193
193
  # <lafcadio_class_definition name="Message">
194
- # <field name="subject" class="TextField" />
195
- # <field name="body" class="TextField" />
196
- # <field name="author" class="LinkField" linked_type="User" />
197
- # <field name="recipient" class="LinkField" linked_type="User" />
194
+ # <field name="subject" class="StringField" />
195
+ # <field name="body" class="StringField" />
196
+ # <field name="author" class="DomainObjectField" linked_type="User" />
197
+ # <field name="recipient" class="DomainObjectField" linked_type="User" />
198
198
  # <field name="dateSent" class="DateField" />
199
199
  # </lafcadio_class_definition>
200
200
  #
@@ -251,6 +251,9 @@ module Lafcadio
251
251
  hash[key] = pk_field
252
252
  }
253
253
  @@sql_primary_keys = Hash.new( 'pk_id' )
254
+ @@default_field_setup_hashes = Hash.new { |hash, key|
255
+ hash[key] = Hash.new( {} )
256
+ }
254
257
 
255
258
  COMMIT_ADD = 1
256
259
  COMMIT_EDIT = 2
@@ -258,11 +261,15 @@ module Lafcadio
258
261
 
259
262
  include DomainComparable
260
263
 
264
+ def self.[]( pk_id ); get( pk_id ); end
265
+
261
266
  def self.abstract_subclasses #:nodoc:
262
267
  require 'lafcadio/domain'
263
268
  [ MapObject ]
264
269
  end
265
270
 
271
+ def self.all; ObjectStore.get_object_store.get_all( self ); end
272
+
266
273
  # Returns an array of all fields defined for this class and all concrete
267
274
  # superclasses.
268
275
  def self.all_fields
@@ -278,22 +285,32 @@ module Lafcadio
278
285
  unless class_fields
279
286
  @@class_fields[self] = self.get_class_fields
280
287
  class_fields = @@class_fields[self]
288
+ class_fields.each do |class_field|
289
+ begin
290
+ undef_method class_field.name.to_sym
291
+ rescue NameError
292
+ # not defined globally or in an included Module, skip it
293
+ end
294
+ end
281
295
  end
282
296
  class_fields
283
297
  end
284
298
 
285
299
  def self.create_field( field_class, *args )
286
300
  class_fields = @@class_fields[self]
301
+ if args.last.is_a? Hash
302
+ att_hash = args.last
303
+ else
304
+ att_hash = @@default_field_setup_hashes[self][field_class].clone
305
+ end
287
306
  if class_fields.nil?
288
307
  class_fields = [ @@pk_fields[self] ]
289
308
  @@class_fields[self] = class_fields
290
309
  end
291
- if field_class == LinkField
292
- att_hash = args.last.is_a?( Hash ) ? args.last : {}
310
+ if field_class == DomainObjectField
293
311
  att_hash['linked_type'] = args.first
294
312
  att_hash['name'] = args[1] if args[1] and !args[1].is_a? Hash
295
313
  else
296
- att_hash = args[1] || {}
297
314
  name = args.first
298
315
  att_hash['name'] = name == String ? name : name.to_s
299
316
  end
@@ -305,13 +322,17 @@ module Lafcadio
305
322
  class_fields << field
306
323
  end
307
324
 
325
+ def self.default_field_setup_hash( field_class, hash )
326
+ @@default_field_setup_hashes[self][field_class] = hash
327
+ end
328
+
308
329
  def self.dependent_classes #:nodoc:
309
330
  dependent_classes = {}
310
331
  DomainObject.subclasses.each { |aClass|
311
332
  if aClass != DomainObjectProxy &&
312
333
  (!DomainObject.abstract_subclasses.index(aClass))
313
334
  aClass.class_fields.each { |field|
314
- if ( field.is_a?( LinkField ) &&
335
+ if ( field.is_a?( DomainObjectField ) &&
315
336
  field.linked_type == self.domain_class )
316
337
  dependent_classes[aClass] = field
317
338
  end
@@ -320,6 +341,15 @@ module Lafcadio
320
341
  }
321
342
  dependent_classes
322
343
  end
344
+
345
+ def self.exist?( search_term, field_name = :pk_id )
346
+ query = Query.infer( self ) { |dobj|
347
+ dobj.send( field_name ).equals( search_term )
348
+ }
349
+ !ObjectStore.get_object_store.get_subset( query ).empty?
350
+ end
351
+
352
+ def self.first; all.first; end
323
353
 
324
354
  def self.get_class_field(fieldName) #:nodoc:
325
355
  field = nil
@@ -392,7 +422,7 @@ module Lafcadio
392
422
 
393
423
  def self.get_link_field( linked_domain_class ) # :nodoc:
394
424
  class_fields.find { |field|
395
- field.is_a? LinkField and field.linked_type == linked_domain_class
425
+ field.is_a? DomainObjectField and field.linked_type == linked_domain_class
396
426
  }
397
427
  end
398
428
 
@@ -408,14 +438,18 @@ module Lafcadio
408
438
  (self != DomainObject && abstract_subclasses.index(self).nil?)
409
439
  end
410
440
 
441
+ def self.last; all.last; end
442
+
411
443
  def self.method_missing( methodId, *args ) #:nodoc:
412
444
  method_name = methodId.id2name
413
445
  if method_name == 'get'
414
446
  if block_given?
415
447
  query = Query.infer( self ) { |dobj| yield( dobj ) }
416
448
  ObjectStore.get_object_store.get_subset( query )
417
- else
449
+ elsif args.size == 1
418
450
  ObjectStore.get_object_store.get( self, *args )
451
+ else
452
+ ObjectStore.get_object_store.get_filtered( self.name, *args )
419
453
  end
420
454
  else
421
455
  maybe_field_class_name = method_name.underscore_to_camel_case + 'Field'
@@ -423,10 +457,34 @@ module Lafcadio
423
457
  field_class = Lafcadio.const_get( maybe_field_class_name )
424
458
  create_field( field_class, *args )
425
459
  rescue NameError
426
- super
460
+ singular = method_name.singular
461
+ if singular
462
+ maybe_field_class_name = singular.underscore_to_camel_case + 'Field'
463
+ begin
464
+ field_class = Lafcadio.const_get( maybe_field_class_name )
465
+ arg = args.shift
466
+ until args.empty?
467
+ next_arg = args.shift
468
+ if next_arg.is_a? String or next_arg.is_a? Symbol
469
+ create_field( field_class, arg )
470
+ arg = next_arg
471
+ else
472
+ create_field( field_class, arg, next_arg )
473
+ arg = args.shift
474
+ end
475
+ end
476
+ create_field( field_class, arg ) unless arg.nil?
477
+ rescue NameError
478
+ super
479
+ end
480
+ else
481
+ super
482
+ end
427
483
  end
428
484
  end
429
485
  end
486
+
487
+ def self.only; all.only; end
430
488
 
431
489
  def self.domain_class #:nodoc:
432
490
  self
@@ -494,7 +552,7 @@ module Lafcadio
494
552
  if (!xmlParser.nil? && table_name = xmlParser.table_name)
495
553
  table_name
496
554
  else
497
- English.plural( self.basename.camel_case_to_underscore )
555
+ self.basename.camel_case_to_underscore.plural
498
556
  end
499
557
  end
500
558
  end
@@ -545,6 +603,7 @@ module Lafcadio
545
603
  @error_messages = []
546
604
  @fields = {}
547
605
  @fields_set = []
606
+ @original_values = OriginalValuesHash.new( @fieldHash )
548
607
  check_fields = LafcadioConfig.new()['checkFields']
549
608
  verify if %w( onInstantiate onAllStates ).include?( check_fields )
550
609
  end
@@ -570,6 +629,11 @@ module Lafcadio
570
629
  end
571
630
  @delete = value
572
631
  end
632
+
633
+ def delete!
634
+ self.delete = true
635
+ commit
636
+ end
573
637
 
574
638
  def get_field( field ) #:nodoc:
575
639
  unless @fields_set.include?( field )
@@ -603,12 +667,15 @@ module Lafcadio
603
667
  set_field( field, args.first )
604
668
  elsif ( field = get_getter_field( methId ) )
605
669
  get_field( field )
606
- elsif ( methId.to_s =~ /^get_/ and
607
- ObjectStore.get_object_store.respond_to?( methId ) )
608
- args = [ self ].concat( args )
609
- ObjectStore.get_object_store.send( methId, *args )
610
670
  else
611
- super( methId, *args )
671
+ new_symbol = ( 'get_' + methId.id2name ).to_sym
672
+ object_store = ObjectStore.get_object_store
673
+ if object_store.respond_to? new_symbol
674
+ args = [ self ].concat args
675
+ object_store.send( 'get_' + methId.id2name, *args )
676
+ else
677
+ super( methId, *args )
678
+ end
612
679
  end
613
680
  end
614
681
 
@@ -632,7 +699,7 @@ module Lafcadio
632
699
  end
633
700
 
634
701
  def set_field( field, value ) #:nodoc:
635
- if field.class <= LinkField
702
+ if field.class <= DomainObjectField
636
703
  if value.class != DomainObjectProxy && value
637
704
  value = DomainObjectProxy.new(value)
638
705
  end
@@ -645,6 +712,11 @@ module Lafcadio
645
712
  @fields_set << field
646
713
  end
647
714
 
715
+ def update!( changes )
716
+ changes.each do |sym, value| self.send( sym.to_s + '=', value ); end
717
+ commit
718
+ end
719
+
648
720
  def verify
649
721
  if ObjectStore.get_object_store.mock?
650
722
  self.class.get_class_fields.each { |field|
@@ -652,6 +724,10 @@ module Lafcadio
652
724
  }
653
725
  end
654
726
  end
727
+
728
+ class OriginalValuesHash < DelegateClass( Hash )
729
+ def []=( key, val ); raise NoMethodError; end
730
+ end
655
731
  end
656
732
 
657
733
  # Any domain class that is used mostly to map between two other domain