lafcadio 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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