lafcadio 0.6.6 → 0.7.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/domain.rb +11 -22
- data/lib/lafcadio/domain.rb~ +10 -16
- data/lib/lafcadio/mock.rb +10 -13
- data/lib/lafcadio/mock.rb~ +7 -6
- data/lib/lafcadio/objectField.rb +1 -1
- data/lib/lafcadio/objectStore.rb +27 -12
- data/lib/lafcadio/objectStore.rb~ +7 -3
- data/lib/lafcadio/query.rb +71 -17
- data/lib/lafcadio/query.rb~ +22 -11
- data/lib/lafcadio/test/testconfig.dat~ +13 -0
- data/lib/lafcadio/util.rb +8 -15
- data/lib/lafcadio/util.rb~ +8 -11
- metadata +5 -6
- data/lib/lafcadio/objectField.rb~ +0 -561
data/lib/lafcadio.rb
CHANGED
data/lib/lafcadio.rb~
CHANGED
data/lib/lafcadio/domain.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'extensions/module'
|
2
1
|
require 'lafcadio/objectField'
|
3
2
|
require 'lafcadio/util'
|
4
3
|
require 'rexml/document'
|
@@ -278,13 +277,6 @@ module Lafcadio
|
|
278
277
|
unless class_fields
|
279
278
|
@@class_fields[self] = self.get_class_fields
|
280
279
|
class_fields = @@class_fields[self]
|
281
|
-
class_fields.each do |class_field|
|
282
|
-
begin
|
283
|
-
undef_method class_field.name.to_sym
|
284
|
-
rescue NameError
|
285
|
-
# not defined globally or in an included Module, skip it
|
286
|
-
end
|
287
|
-
end
|
288
280
|
end
|
289
281
|
class_fields
|
290
282
|
end
|
@@ -295,15 +287,13 @@ module Lafcadio
|
|
295
287
|
class_fields = [ @@pk_fields[self] ]
|
296
288
|
@@class_fields[self] = class_fields
|
297
289
|
end
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
class_fields << field
|
306
|
-
end
|
290
|
+
att_hash['name'] = name
|
291
|
+
field = field_class.instantiate_with_parameters( self, att_hash )
|
292
|
+
att_hash.each { |field_name, value|
|
293
|
+
setter = field_name + '='
|
294
|
+
field.send( setter, value ) if field.respond_to?( setter )
|
295
|
+
}
|
296
|
+
class_fields << field
|
307
297
|
end
|
308
298
|
|
309
299
|
def self.dependent_classes #:nodoc:
|
@@ -339,8 +329,6 @@ module Lafcadio
|
|
339
329
|
def self.get_class_fields
|
340
330
|
if self.methods( false ).include?( 'get_class_fields' )
|
341
331
|
[ @@pk_fields[ self ] ]
|
342
|
-
elsif abstract_subclasses.include?( self )
|
343
|
-
[]
|
344
332
|
else
|
345
333
|
xmlParser = try_load_xml_parser
|
346
334
|
if xmlParser
|
@@ -360,7 +348,7 @@ module Lafcadio
|
|
360
348
|
[]
|
361
349
|
end
|
362
350
|
end
|
363
|
-
|
351
|
+
|
364
352
|
def self.get_field( fieldName ) #:nodoc:
|
365
353
|
aDomainClass = self
|
366
354
|
field = nil
|
@@ -371,7 +359,7 @@ module Lafcadio
|
|
371
359
|
if field
|
372
360
|
field
|
373
361
|
else
|
374
|
-
errStr = "Couldn't find field \"#{
|
362
|
+
errStr = "Couldn't find field \"#{ field }\" in " +
|
375
363
|
"#{ self } domain class"
|
376
364
|
raise( MissingError, errStr, caller )
|
377
365
|
end
|
@@ -405,7 +393,8 @@ module Lafcadio
|
|
405
393
|
|
406
394
|
def self.method_missing( methodId, *args ) #:nodoc:
|
407
395
|
method_name = methodId.id2name
|
408
|
-
maybe_field_class_name = method_name.
|
396
|
+
maybe_field_class_name = ( method_name.gsub( /^(.)/ ) { $&.upcase } ) +
|
397
|
+
'Field'
|
409
398
|
field_class = Lafcadio.const_get( maybe_field_class_name )
|
410
399
|
create_field( field_class, args[0], args[1] || {} )
|
411
400
|
end
|
data/lib/lafcadio/domain.rb~
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'extensions/module'
|
2
1
|
require 'lafcadio/objectField'
|
3
2
|
require 'lafcadio/util'
|
4
3
|
require 'rexml/document'
|
@@ -278,13 +277,6 @@ module Lafcadio
|
|
278
277
|
unless class_fields
|
279
278
|
@@class_fields[self] = self.get_class_fields
|
280
279
|
class_fields = @@class_fields[self]
|
281
|
-
class_fields.each do |class_field|
|
282
|
-
begin
|
283
|
-
undef_method class_field.name.to_sym
|
284
|
-
rescue NameError
|
285
|
-
# not defined globally or in an included Module, skip it
|
286
|
-
end
|
287
|
-
end
|
288
280
|
end
|
289
281
|
class_fields
|
290
282
|
end
|
@@ -337,8 +329,6 @@ module Lafcadio
|
|
337
329
|
def self.get_class_fields
|
338
330
|
if self.methods( false ).include?( 'get_class_fields' )
|
339
331
|
[ @@pk_fields[ self ] ]
|
340
|
-
elsif abstract_subclasses.include?( self )
|
341
|
-
[]
|
342
332
|
else
|
343
333
|
xmlParser = try_load_xml_parser
|
344
334
|
if xmlParser
|
@@ -352,13 +342,16 @@ module Lafcadio
|
|
352
342
|
end
|
353
343
|
|
354
344
|
def self.get_domain_dirs #:nodoc:
|
355
|
-
|
356
|
-
|
345
|
+
config = LafcadioConfig.new
|
346
|
+
classPath = config['classpath']
|
347
|
+
domainDirStr = config['domainDirs']
|
348
|
+
if domainDirStr
|
349
|
+
domainDirs = domainDirStr.split(',')
|
357
350
|
else
|
358
|
-
[]
|
351
|
+
domainDirs = [ classPath + 'domain/' ]
|
359
352
|
end
|
360
353
|
end
|
361
|
-
|
354
|
+
|
362
355
|
def self.get_field( fieldName ) #:nodoc:
|
363
356
|
aDomainClass = self
|
364
357
|
field = nil
|
@@ -369,7 +362,7 @@ module Lafcadio
|
|
369
362
|
if field
|
370
363
|
field
|
371
364
|
else
|
372
|
-
errStr = "Couldn't find field \"#{
|
365
|
+
errStr = "Couldn't find field \"#{ field }\" in " +
|
373
366
|
"#{ self } domain class"
|
374
367
|
raise( MissingError, errStr, caller )
|
375
368
|
end
|
@@ -403,7 +396,8 @@ module Lafcadio
|
|
403
396
|
|
404
397
|
def self.method_missing( methodId, *args ) #:nodoc:
|
405
398
|
method_name = methodId.id2name
|
406
|
-
maybe_field_class_name = method_name.
|
399
|
+
maybe_field_class_name = ( method_name.gsub( /^(.)/ ) { $&.upcase } ) +
|
400
|
+
'Field'
|
407
401
|
field_class = Lafcadio.const_get( maybe_field_class_name )
|
408
402
|
create_field( field_class, args[0], args[1] || {} )
|
409
403
|
end
|
data/lib/lafcadio/mock.rb
CHANGED
@@ -11,6 +11,9 @@ module Lafcadio
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def commit(db_object)
|
14
|
+
if db_object.pk_id and !db_object.pk_id.is_a?( Integer )
|
15
|
+
raise ArgumentError
|
16
|
+
end
|
14
17
|
objects_by_domain_class = get_objects_by_domain_class(
|
15
18
|
db_object.domain_class
|
16
19
|
)
|
@@ -28,7 +31,7 @@ module Lafcadio
|
|
28
31
|
end
|
29
32
|
|
30
33
|
def get_collection_by_query(query)
|
31
|
-
@query_count[query] += 1
|
34
|
+
@query_count[query.to_sql] += 1
|
32
35
|
objects = []
|
33
36
|
_get_all( query.domain_class ).each { |dbObj|
|
34
37
|
if query.condition
|
@@ -37,14 +40,12 @@ module Lafcadio
|
|
37
40
|
objects << dbObj
|
38
41
|
end
|
39
42
|
}
|
43
|
+
if (range = query.limit)
|
44
|
+
objects = objects[0..(range.last - range.first)]
|
45
|
+
end
|
40
46
|
if ( order_by = query.order_by )
|
41
47
|
objects = objects.sort_by { |dobj| dobj.send( order_by ) }
|
42
48
|
objects.reverse! if query.order_by_order == Query::DESC
|
43
|
-
else
|
44
|
-
objects = objects.sort_by { |dobj| dobj.pk_id }
|
45
|
-
end
|
46
|
-
if (range = query.limit)
|
47
|
-
objects = objects[range]
|
48
49
|
end
|
49
50
|
objects
|
50
51
|
end
|
@@ -74,14 +75,10 @@ module Lafcadio
|
|
74
75
|
|
75
76
|
def group_query( query )
|
76
77
|
if query.class == Query::Max
|
77
|
-
|
78
|
-
|
79
|
-
dobjs = dobjs_by_pk_id.values.sort_by { |dobj|
|
80
|
-
dobj.send( query.field_name )
|
81
|
-
}
|
82
|
-
[ dobjs.last.send( query.field_name ) ]
|
78
|
+
if ( query.field_name == 'pk_id' || query.field_name == 'rate' )
|
79
|
+
query.collect( @objects[query.domain_class].values )
|
83
80
|
else
|
84
|
-
|
81
|
+
raise "Can't handle query with sql '#{ query.to_sql }'"
|
85
82
|
end
|
86
83
|
end
|
87
84
|
end
|
data/lib/lafcadio/mock.rb~
CHANGED
@@ -11,6 +11,9 @@ module Lafcadio
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def commit(db_object)
|
14
|
+
if db_object.pk_id and !db_object.pk_id.is_a?( Integer )
|
15
|
+
raise ArgumentError
|
16
|
+
end
|
14
17
|
objects_by_domain_class = get_objects_by_domain_class(
|
15
18
|
db_object.domain_class
|
16
19
|
)
|
@@ -28,7 +31,7 @@ module Lafcadio
|
|
28
31
|
end
|
29
32
|
|
30
33
|
def get_collection_by_query(query)
|
31
|
-
@query_count[query] += 1
|
34
|
+
@query_count[query.to_sql] += 1
|
32
35
|
objects = []
|
33
36
|
_get_all( query.domain_class ).each { |dbObj|
|
34
37
|
if query.condition
|
@@ -37,14 +40,12 @@ module Lafcadio
|
|
37
40
|
objects << dbObj
|
38
41
|
end
|
39
42
|
}
|
43
|
+
if (range = query.limit)
|
44
|
+
objects = objects[0..(range.last - range.first)]
|
45
|
+
end
|
40
46
|
if ( order_by = query.order_by )
|
41
47
|
objects = objects.sort_by { |dobj| dobj.send( order_by ) }
|
42
48
|
objects.reverse! if query.order_by_order == Query::DESC
|
43
|
-
else
|
44
|
-
objects = objects.sort_by { |dobj| dobj.pk_id }
|
45
|
-
end
|
46
|
-
if (range = query.limit)
|
47
|
-
objects = objects[range]
|
48
49
|
end
|
49
50
|
objects
|
50
51
|
end
|
data/lib/lafcadio/objectField.rb
CHANGED
@@ -424,7 +424,7 @@ module Lafcadio
|
|
424
424
|
unless name
|
425
425
|
linked_type.name =~ /::/
|
426
426
|
name = $' || linked_type.name
|
427
|
-
name = name.
|
427
|
+
name = name.decapitalize
|
428
428
|
end
|
429
429
|
super( domain_class, name )
|
430
430
|
( @linked_type, @delete_cascade ) = linked_type, delete_cascade
|
data/lib/lafcadio/objectStore.rb
CHANGED
@@ -11,10 +11,9 @@ module Lafcadio
|
|
11
11
|
|
12
12
|
attr_reader :commit_type, :db_object
|
13
13
|
|
14
|
-
def initialize(db_object, dbBridge
|
14
|
+
def initialize(db_object, dbBridge)
|
15
15
|
@db_object = db_object
|
16
16
|
@dbBridge = dbBridge
|
17
|
-
@cache = cache
|
18
17
|
@objectStore = ObjectStore.get_object_store
|
19
18
|
@commit_type = nil
|
20
19
|
end
|
@@ -29,7 +28,6 @@ module Lafcadio
|
|
29
28
|
unless @db_object.pk_id
|
30
29
|
@db_object.pk_id = @dbBridge.last_pk_id_inserted
|
31
30
|
end
|
32
|
-
@cache.update_after_commit self
|
33
31
|
@db_object.post_commit_trigger
|
34
32
|
end
|
35
33
|
|
@@ -131,8 +129,12 @@ module Lafcadio
|
|
131
129
|
|
132
130
|
def group_query( query )
|
133
131
|
execute_select( query.to_sql )[0].collect { |val|
|
134
|
-
|
135
|
-
|
132
|
+
if query.field_name != query.domain_class.sql_primary_key_name
|
133
|
+
a_field = query.domain_class.get_field( query.field_name )
|
134
|
+
a_field.value_from_sql( val )
|
135
|
+
else
|
136
|
+
val.to_i
|
137
|
+
end
|
136
138
|
}
|
137
139
|
end
|
138
140
|
|
@@ -441,7 +443,7 @@ module Lafcadio
|
|
441
443
|
def get_db_bridge; @dbBridge; end
|
442
444
|
|
443
445
|
def get_field_name( domain_object )
|
444
|
-
domain_object.domain_class.basename.
|
446
|
+
domain_object.domain_class.basename.decapitalize
|
445
447
|
end
|
446
448
|
|
447
449
|
def get_filtered(domain_class_name, searchTerm, fieldName = nil) #:nodoc:
|
@@ -538,8 +540,9 @@ module Lafcadio
|
|
538
540
|
end
|
539
541
|
|
540
542
|
def commit( db_object )
|
541
|
-
committer = Committer.new db_object, @dbBridge
|
543
|
+
committer = Committer.new db_object, @dbBridge
|
542
544
|
committer.execute
|
545
|
+
update_after_commit( committer )
|
543
546
|
end
|
544
547
|
|
545
548
|
# Flushes a domain object.
|
@@ -570,11 +573,23 @@ module Lafcadio
|
|
570
573
|
|
571
574
|
def get_by_query( query )
|
572
575
|
unless @collections_by_query[query]
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
576
|
+
superset_query, pk_ids =
|
577
|
+
@collections_by_query.find { |other_query, pk_ids|
|
578
|
+
query.implies?( other_query )
|
579
|
+
}
|
580
|
+
if pk_ids
|
581
|
+
@collections_by_query[query] = ( pk_ids.collect { |pk_id|
|
582
|
+
get( query.domain_class, pk_id )
|
583
|
+
} ).select { |dobj| query.object_meets( dobj ) }.collect { |dobj|
|
584
|
+
dobj.pk_id
|
585
|
+
}
|
586
|
+
elsif @collections_by_query.values
|
587
|
+
newObjects = @dbBridge.get_collection_by_query(query)
|
588
|
+
newObjects.each { |dbObj| save dbObj }
|
589
|
+
@collections_by_query[query] = newObjects.collect { |dobj|
|
590
|
+
dobj.pk_id
|
591
|
+
}
|
592
|
+
end
|
578
593
|
end
|
579
594
|
collection = []
|
580
595
|
@collections_by_query[query].each { |pk_id|
|
@@ -129,8 +129,12 @@ module Lafcadio
|
|
129
129
|
|
130
130
|
def group_query( query )
|
131
131
|
execute_select( query.to_sql )[0].collect { |val|
|
132
|
-
|
133
|
-
|
132
|
+
if query.field_name != query.domain_class.sql_primary_key_name
|
133
|
+
a_field = query.domain_class.get_field( query.field_name )
|
134
|
+
a_field.value_from_sql( val )
|
135
|
+
else
|
136
|
+
val.to_i
|
137
|
+
end
|
134
138
|
}
|
135
139
|
end
|
136
140
|
|
@@ -439,7 +443,7 @@ module Lafcadio
|
|
439
443
|
def get_db_bridge; @dbBridge; end
|
440
444
|
|
441
445
|
def get_field_name( domain_object )
|
442
|
-
domain_object.domain_class.basename.
|
446
|
+
domain_object.domain_class.basename.decapitalize
|
443
447
|
end
|
444
448
|
|
445
449
|
def get_filtered(domain_class_name, searchTerm, fieldName = nil) #:nodoc:
|
data/lib/lafcadio/query.rb
CHANGED
@@ -140,17 +140,30 @@ module Lafcadio
|
|
140
140
|
def limit_clause
|
141
141
|
"limit #{ @limit.begin }, #{ @limit.end - @limit.begin + 1 }" if @limit
|
142
142
|
end
|
143
|
+
|
144
|
+
def object_meets( dobj ); @condition.object_meets( dobj ); end
|
143
145
|
|
144
146
|
def or( &action ); compound( CompoundCondition::OR, action ); end
|
145
147
|
|
146
148
|
def order_clause
|
147
149
|
if @order_by
|
148
|
-
|
149
|
-
clause = "order by #{ order_by_field.db_field_name } "
|
150
|
+
clause = "order by #{ @order_by } "
|
150
151
|
clause += @order_by_order == ASC ? 'asc' : 'desc'
|
151
152
|
clause
|
152
153
|
end
|
153
154
|
end
|
155
|
+
|
156
|
+
def implies?( other_query )
|
157
|
+
if other_query == self
|
158
|
+
true
|
159
|
+
elsif @domain_class == other_query.domain_class
|
160
|
+
if other_query.condition.nil? and !self.condition.nil?
|
161
|
+
true
|
162
|
+
else
|
163
|
+
self.condition and self.condition.implies?( other_query.condition )
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
154
167
|
|
155
168
|
def sql_primary_key_field(domain_class)
|
156
169
|
"#{ domain_class.table_name }.#{ domain_class.sql_primary_key_name }"
|
@@ -208,9 +221,34 @@ module Lafcadio
|
|
208
221
|
end
|
209
222
|
end
|
210
223
|
|
224
|
+
def implies?( other_condition )
|
225
|
+
self.eql?( other_condition ) or (
|
226
|
+
other_condition.respond_to?( :implied_by? ) and
|
227
|
+
other_condition.implied_by?( self )
|
228
|
+
)
|
229
|
+
end
|
230
|
+
|
211
231
|
def db_field_name; get_field.db_table_and_field_name; end
|
212
232
|
|
213
|
-
def
|
233
|
+
def eql?( other_cond )
|
234
|
+
other_cond.is_a?( Condition ) and other_cond.to_sql == to_sql
|
235
|
+
end
|
236
|
+
|
237
|
+
def get_field
|
238
|
+
a_domain_class = @domain_class
|
239
|
+
field = nil
|
240
|
+
while ( a_domain_class < DomainObject ) && !field
|
241
|
+
field = a_domain_class.get_class_field( @fieldName )
|
242
|
+
a_domain_class = a_domain_class.superclass
|
243
|
+
end
|
244
|
+
if field
|
245
|
+
field
|
246
|
+
else
|
247
|
+
errStr = "Couldn't find field \"#{ @fieldName }\" in " +
|
248
|
+
"#{ @domain_class } domain class"
|
249
|
+
raise( MissingError, errStr, caller )
|
250
|
+
end
|
251
|
+
end
|
214
252
|
|
215
253
|
def query; Query.new( @domain_class, self ); end
|
216
254
|
|
@@ -272,22 +310,38 @@ module Lafcadio
|
|
272
310
|
class CompoundCondition < Condition #:nodoc:
|
273
311
|
AND = 1
|
274
312
|
OR = 2
|
275
|
-
|
276
|
-
def initialize(
|
277
|
-
if( [ AND, OR ].index(
|
278
|
-
@
|
279
|
-
|
313
|
+
|
314
|
+
def initialize(*conditions)
|
315
|
+
if( [ AND, OR ].index(conditions.last) )
|
316
|
+
@compound_type = conditions.last
|
317
|
+
conditions.pop
|
280
318
|
else
|
281
|
-
@
|
319
|
+
@compound_type = AND
|
282
320
|
end
|
283
|
-
@conditions =
|
284
|
-
|
321
|
+
@conditions = conditions
|
322
|
+
@domain_class = conditions[0].domain_class
|
323
|
+
end
|
324
|
+
|
325
|
+
def implied_by?( other_condition )
|
326
|
+
@compound_type == OR && @conditions.any? { |cond|
|
327
|
+
cond.implies?( other_condition )
|
285
328
|
}
|
286
|
-
|
329
|
+
end
|
330
|
+
|
331
|
+
def implies?( other_condition )
|
332
|
+
super( other_condition ) or (
|
333
|
+
@compound_type == AND and @conditions.any? { |cond|
|
334
|
+
cond.implies?( other_condition )
|
335
|
+
}
|
336
|
+
) or (
|
337
|
+
@compound_type == OR and @conditions.all? { |cond|
|
338
|
+
cond.implies?( other_condition )
|
339
|
+
}
|
340
|
+
)
|
287
341
|
end
|
288
342
|
|
289
343
|
def object_meets(anObj)
|
290
|
-
if @
|
344
|
+
if @compound_type == AND
|
291
345
|
@conditions.inject( true ) { |result, cond|
|
292
346
|
result && cond.object_meets( anObj )
|
293
347
|
}
|
@@ -299,7 +353,7 @@ module Lafcadio
|
|
299
353
|
end
|
300
354
|
|
301
355
|
def to_sql
|
302
|
-
booleanString = @
|
356
|
+
booleanString = @compound_type == AND ? 'and' : 'or'
|
303
357
|
subSqlStrings = @conditions.collect { |cond| cond.to_sql }
|
304
358
|
"(#{ subSqlStrings.join(" #{ booleanString } ") })"
|
305
359
|
end
|
@@ -415,11 +469,11 @@ module Lafcadio
|
|
415
469
|
|
416
470
|
def get_regexp
|
417
471
|
if @matchType == PRE_AND_POST
|
418
|
-
Regexp.new(
|
472
|
+
Regexp.new(@searchTerm)
|
419
473
|
elsif @matchType == PRE_ONLY
|
420
|
-
Regexp.new(
|
474
|
+
Regexp.new(@searchTerm.to_s + "$")
|
421
475
|
elsif @matchType == POST_ONLY
|
422
|
-
Regexp.new(
|
476
|
+
Regexp.new("^" + @searchTerm)
|
423
477
|
end
|
424
478
|
end
|
425
479
|
|
data/lib/lafcadio/query.rb~
CHANGED
@@ -145,8 +145,7 @@ module Lafcadio
|
|
145
145
|
|
146
146
|
def order_clause
|
147
147
|
if @order_by
|
148
|
-
|
149
|
-
clause = "order by #{ order_by_field.db_field_name } "
|
148
|
+
clause = "order by #{ @order_by } "
|
150
149
|
clause += @order_by_order == ASC ? 'asc' : 'desc'
|
151
150
|
clause
|
152
151
|
end
|
@@ -210,7 +209,21 @@ module Lafcadio
|
|
210
209
|
|
211
210
|
def db_field_name; get_field.db_table_and_field_name; end
|
212
211
|
|
213
|
-
def get_field
|
212
|
+
def get_field
|
213
|
+
a_domain_class = @domain_class
|
214
|
+
field = nil
|
215
|
+
while ( a_domain_class < DomainObject ) && !field
|
216
|
+
field = a_domain_class.get_class_field( @fieldName )
|
217
|
+
a_domain_class = a_domain_class.superclass
|
218
|
+
end
|
219
|
+
if field
|
220
|
+
field
|
221
|
+
else
|
222
|
+
errStr = "Couldn't find field \"#{ @fieldName }\" in " +
|
223
|
+
"#{ @domain_class } domain class"
|
224
|
+
raise( MissingError, errStr, caller )
|
225
|
+
end
|
226
|
+
end
|
214
227
|
|
215
228
|
def query; Query.new( @domain_class, self ); end
|
216
229
|
|
@@ -273,17 +286,15 @@ module Lafcadio
|
|
273
286
|
AND = 1
|
274
287
|
OR = 2
|
275
288
|
|
276
|
-
def initialize(
|
277
|
-
if( [ AND, OR ].index(
|
278
|
-
@compoundType =
|
279
|
-
|
289
|
+
def initialize(*conditions)
|
290
|
+
if( [ AND, OR ].index(conditions.last) )
|
291
|
+
@compoundType = conditions.last
|
292
|
+
conditions.pop
|
280
293
|
else
|
281
294
|
@compoundType = AND
|
282
295
|
end
|
283
|
-
@conditions =
|
284
|
-
|
285
|
-
}
|
286
|
-
@domain_class = @conditions[0].domain_class
|
296
|
+
@conditions = conditions
|
297
|
+
@domain_class = conditions[0].domain_class
|
287
298
|
end
|
288
299
|
|
289
300
|
def object_meets(anObj)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
dbuser:test
|
2
|
+
dbpassword:password
|
3
|
+
dbname:test
|
4
|
+
dbhost:localhost
|
5
|
+
adminEmail:john.doe@email.com
|
6
|
+
siteName:Site Name
|
7
|
+
url:http://test.url
|
8
|
+
classpath:lafcadio/
|
9
|
+
logdir:../test/testOutput/
|
10
|
+
domainDirs:../test/mock/domain/
|
11
|
+
domainFiles:../test/mock/domain.rb
|
12
|
+
logSql:n
|
13
|
+
classDefinitionDir:../test/testData
|
data/lib/lafcadio/util.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'delegate'
|
2
|
-
require 'lafcadio/depend'
|
3
2
|
require 'singleton'
|
4
3
|
|
5
4
|
module Lafcadio
|
@@ -67,16 +66,14 @@ module Lafcadio
|
|
67
66
|
class ContextualService
|
68
67
|
def self.flush; Context.instance.set_resource( self, nil ); end
|
69
68
|
|
70
|
-
def self.method_missing(
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
if target
|
79
|
-
Context.instance.send( target, self, *args )
|
69
|
+
def self.method_missing( methodId, *args )
|
70
|
+
methodName = methodId.id2name
|
71
|
+
if methodName =~ /^get_(.*)/ || methodName =~ /^set_(.*)/
|
72
|
+
if methodName =~ /^get_(.*)/
|
73
|
+
Context.instance.get_resource( self )
|
74
|
+
else
|
75
|
+
Context.instance.set_resource( self, *args )
|
76
|
+
end
|
80
77
|
else
|
81
78
|
super
|
82
79
|
end
|
@@ -133,12 +130,8 @@ module Lafcadio
|
|
133
130
|
consonantYPattern = Regexp.new("([^aeiou])y$", Regexp::IGNORECASE)
|
134
131
|
if singular =~ consonantYPattern
|
135
132
|
singular.gsub consonantYPattern, '\1ies'
|
136
|
-
elsif singular =~ /^(.*)xis$/
|
137
|
-
$1 + 'xes'
|
138
133
|
elsif singular =~ /[xs]$/
|
139
134
|
singular + "es"
|
140
|
-
elsif singular =~ /(.*)tum$/
|
141
|
-
$1 + 'ta'
|
142
135
|
else
|
143
136
|
singular + "s"
|
144
137
|
end
|
data/lib/lafcadio/util.rb~
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'delegate'
|
2
|
-
require 'lafcadio/depend'
|
3
2
|
require 'singleton'
|
4
3
|
|
5
4
|
module Lafcadio
|
@@ -67,16 +66,14 @@ module Lafcadio
|
|
67
66
|
class ContextualService
|
68
67
|
def self.flush; Context.instance.set_resource( self, nil ); end
|
69
68
|
|
70
|
-
def self.method_missing(
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
if target
|
79
|
-
Context.instance.send( target, self, *args )
|
69
|
+
def self.method_missing( methodId, *args )
|
70
|
+
methodName = methodId.id2name
|
71
|
+
if methodName =~ /^get_(.*)/ || methodName =~ /^set_(.*)/
|
72
|
+
if methodName =~ /^get_(.*)/
|
73
|
+
Context.instance.get_resource( self )
|
74
|
+
else
|
75
|
+
Context.instance.set_resource( self, *args )
|
76
|
+
end
|
80
77
|
else
|
81
78
|
super
|
82
79
|
end
|
metadata
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.8.
|
2
|
+
rubygems_version: 0.8.1
|
3
3
|
specification_version: 1
|
4
4
|
name: lafcadio
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2005-
|
6
|
+
version: 0.7.0
|
7
|
+
date: 2005-01-20
|
8
8
|
summary: Lafcadio is an object-relational mapping layer
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
|
+
author: Francis Hwang
|
11
12
|
email: sera@fhwang.net
|
12
13
|
homepage: http://lafcadio.rubyforge.org/
|
13
14
|
rubyforge_project:
|
@@ -28,8 +29,6 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
28
29
|
version: 0.0.0
|
29
30
|
version:
|
30
31
|
platform: ruby
|
31
|
-
authors:
|
32
|
-
- Francis Hwang
|
33
32
|
files:
|
34
33
|
- lib/lafcadio
|
35
34
|
- lib/lafcadio.rb
|
@@ -41,7 +40,6 @@ files:
|
|
41
40
|
- lib/lafcadio/mock.rb
|
42
41
|
- lib/lafcadio/mock.rb~
|
43
42
|
- lib/lafcadio/objectField.rb
|
44
|
-
- lib/lafcadio/objectField.rb~
|
45
43
|
- lib/lafcadio/objectStore.rb
|
46
44
|
- lib/lafcadio/objectStore.rb~
|
47
45
|
- lib/lafcadio/query.rb
|
@@ -52,6 +50,7 @@ files:
|
|
52
50
|
- lib/lafcadio/util.rb
|
53
51
|
- lib/lafcadio/util.rb~
|
54
52
|
- lib/lafcadio/test/testconfig.dat
|
53
|
+
- lib/lafcadio/test/testconfig.dat~
|
55
54
|
test_files: []
|
56
55
|
rdoc_options: []
|
57
56
|
extra_rdoc_files: []
|
@@ -1,561 +0,0 @@
|
|
1
|
-
require 'date'
|
2
|
-
require 'lafcadio/dateTime'
|
3
|
-
require 'lafcadio/util'
|
4
|
-
|
5
|
-
module Lafcadio
|
6
|
-
# ObjectField is the abstract base class of any field for domain objects.
|
7
|
-
class ObjectField
|
8
|
-
include Comparable
|
9
|
-
|
10
|
-
attr_reader :name, :domain_class
|
11
|
-
attr_accessor :not_null, :db_field_name
|
12
|
-
|
13
|
-
def self.instantiate_from_xml( domain_class, fieldElt ) #:nodoc:
|
14
|
-
parameters = instantiation_parameters( fieldElt )
|
15
|
-
instantiate_with_parameters( domain_class, parameters )
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
19
|
-
instance = self.new( domain_class, parameters['name'] )
|
20
|
-
if ( db_field_name = parameters['db_field_name'] )
|
21
|
-
instance.db_field_name = db_field_name
|
22
|
-
end
|
23
|
-
instance
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.instantiation_parameters( fieldElt ) #:nodoc:
|
27
|
-
parameters = {}
|
28
|
-
parameters['name'] = fieldElt.attributes['name']
|
29
|
-
parameters['db_field_name'] = fieldElt.attributes['db_field_name']
|
30
|
-
parameters
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.value_type #:nodoc:
|
34
|
-
Object
|
35
|
-
end
|
36
|
-
|
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
|
41
|
-
@name = name
|
42
|
-
@db_field_name = name
|
43
|
-
@not_null = true
|
44
|
-
end
|
45
|
-
|
46
|
-
def <=>(other)
|
47
|
-
if @domain_class == other.domain_class && name == other.name
|
48
|
-
0
|
49
|
-
else
|
50
|
-
object_id <=> other.object_id
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def bind_write?; false; end #:nodoc:
|
55
|
-
|
56
|
-
def db_table_and_field_name
|
57
|
-
"#{ domain_class.table_name }.#{ db_field_name }"
|
58
|
-
end
|
59
|
-
|
60
|
-
def db_will_automatically_write #:nodoc:
|
61
|
-
false
|
62
|
-
end
|
63
|
-
|
64
|
-
# Returns the name that this field is referenced by in the MySQL table. By
|
65
|
-
# default this is the same as the name; to override it, set
|
66
|
-
# ObjectField#db_field_name.
|
67
|
-
def name_for_sql
|
68
|
-
db_field_name
|
69
|
-
end
|
70
|
-
|
71
|
-
def prev_value(pk_id) #:nodoc:
|
72
|
-
prevObject = ObjectStore.get_object_store.get( @domain_class, pk_id )
|
73
|
-
prevObject.send(name)
|
74
|
-
end
|
75
|
-
|
76
|
-
def process_before_verify(value) #:nodoc:
|
77
|
-
value = @default if value == nil
|
78
|
-
value
|
79
|
-
end
|
80
|
-
|
81
|
-
# Returns a string value suitable for committing this field's value to
|
82
|
-
# MySQL.
|
83
|
-
def value_for_sql(value)
|
84
|
-
value || 'null'
|
85
|
-
end
|
86
|
-
|
87
|
-
def verify(value, pk_id) #:nodoc:
|
88
|
-
if value.nil? && not_null
|
89
|
-
raise(
|
90
|
-
FieldValueError,
|
91
|
-
"#{ self.domain_class.name }##{ name } can not be nil.",
|
92
|
-
caller
|
93
|
-
)
|
94
|
-
end
|
95
|
-
verify_non_nil( value, pk_id ) if value
|
96
|
-
end
|
97
|
-
|
98
|
-
def verify_non_nil( value, pk_id )
|
99
|
-
value_type = self.class.value_type
|
100
|
-
unless value.class <= value_type
|
101
|
-
raise(
|
102
|
-
FieldValueError,
|
103
|
-
"#{ domain_class.name }##{ name } needs a " + value_type.name +
|
104
|
-
" value.",
|
105
|
-
caller
|
106
|
-
)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# Given the SQL value string, returns a Ruby-native value.
|
111
|
-
def value_from_sql(string)
|
112
|
-
string
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
# IntegerField represents an integer.
|
117
|
-
class IntegerField < ObjectField
|
118
|
-
def value_from_sql(string) #:nodoc:
|
119
|
-
value = super
|
120
|
-
value ? value.to_i : nil
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# A TextField is expected to contain a string value.
|
125
|
-
class TextField < ObjectField
|
126
|
-
def value_for_sql(value) #:nodoc:
|
127
|
-
if value
|
128
|
-
value = value.gsub(/(\\?')/) { |m| m.length == 1 ? "''" : m }
|
129
|
-
value = value.gsub(/\\/) { '\\\\' }
|
130
|
-
"'#{value}'"
|
131
|
-
else
|
132
|
-
"null"
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# BlobField stores a string value and expects to store its value in a BLOB
|
138
|
-
# field in the database.
|
139
|
-
class BlobField < ObjectField
|
140
|
-
attr_accessor :size
|
141
|
-
|
142
|
-
def self.value_type; String; end
|
143
|
-
|
144
|
-
def bind_write?; true; end #:nodoc:
|
145
|
-
|
146
|
-
def value_for_sql(value); "?"; end #:nodoc:
|
147
|
-
end
|
148
|
-
|
149
|
-
# BooleanField represents a boolean value. By default, it assumes that the
|
150
|
-
# table field represents True and False with the integers 1 and 0. There are
|
151
|
-
# two different ways to change this default.
|
152
|
-
#
|
153
|
-
# First, BooleanField includes a few enumerated defaults. Currently there are
|
154
|
-
# only
|
155
|
-
# * BooleanField::ENUMS_ONE_ZERO (the default, uses integers 1 and 0)
|
156
|
-
# * BooleanField::ENUMS_CAPITAL_YES_NO (uses characters 'Y' and 'N')
|
157
|
-
# In the XML class definition, this field would look like
|
158
|
-
# <field name="field_name" class="BooleanField"
|
159
|
-
# enum_type="ENUMS_CAPITAL_YES_NO"/>
|
160
|
-
# If you're defining a field in Ruby, simply set BooleanField#enum_type to one
|
161
|
-
# of the values.
|
162
|
-
#
|
163
|
-
# For more fine-grained specification you can pass specific values in. Use
|
164
|
-
# this format for the XML class definition:
|
165
|
-
# <field name="field_name" class="BooleanField">
|
166
|
-
# <enums>
|
167
|
-
# <enum key="true">yin</enum>
|
168
|
-
# <enum key="false">tang</enum>
|
169
|
-
# </enums>
|
170
|
-
# </field>
|
171
|
-
# If you're defining the field in Ruby, set BooleanField#enums to a hash.
|
172
|
-
# myBooleanField.enums = { true => 'yin', false => 'yang' }
|
173
|
-
#
|
174
|
-
# +enums+ takes precedence over +enum_type+.
|
175
|
-
class BooleanField < ObjectField
|
176
|
-
ENUMS_ONE_ZERO = 0
|
177
|
-
ENUMS_CAPITAL_YES_NO = 1
|
178
|
-
|
179
|
-
attr_accessor :enum_type, :enums
|
180
|
-
|
181
|
-
def initialize( domain_class, name )
|
182
|
-
super( domain_class, name )
|
183
|
-
@enum_type = ENUMS_ONE_ZERO
|
184
|
-
@enums = nil
|
185
|
-
end
|
186
|
-
|
187
|
-
def false_enum # :nodoc:
|
188
|
-
get_enums[false]
|
189
|
-
end
|
190
|
-
|
191
|
-
def get_enums( value = nil ) # :nodoc:
|
192
|
-
if @enums
|
193
|
-
@enums
|
194
|
-
elsif @enum_type == ENUMS_ONE_ZERO
|
195
|
-
if value.class == String
|
196
|
-
{ true => '1', false => '0' }
|
197
|
-
else
|
198
|
-
{ true => 1, false => 0 }
|
199
|
-
end
|
200
|
-
elsif @enum_type == ENUMS_CAPITAL_YES_NO
|
201
|
-
{ true => 'Y', false => 'N' }
|
202
|
-
else
|
203
|
-
raise MissingError
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def text_enum_type # :nodoc:
|
208
|
-
@enums ? @enums[true].class == String : @enum_type == ENUMS_CAPITAL_YES_NO
|
209
|
-
end
|
210
|
-
|
211
|
-
def true_enum( value = nil ) # :nodoc:
|
212
|
-
get_enums( value )[true]
|
213
|
-
end
|
214
|
-
|
215
|
-
def value_for_sql(value) # :nodoc:
|
216
|
-
if value
|
217
|
-
vfs = true_enum
|
218
|
-
else
|
219
|
-
vfs = false_enum
|
220
|
-
end
|
221
|
-
text_enum_type ? "'#{vfs}'" : vfs
|
222
|
-
end
|
223
|
-
|
224
|
-
def value_from_sql(value, lookupLink = true) # :nodoc:
|
225
|
-
value == true_enum( value )
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
# DateField represents a Date.
|
230
|
-
class DateField < ObjectField
|
231
|
-
def self.value_type # :nodoc:
|
232
|
-
Date
|
233
|
-
end
|
234
|
-
|
235
|
-
def initialize( domain_class, name = "date" )
|
236
|
-
super( domain_class, name )
|
237
|
-
end
|
238
|
-
|
239
|
-
def value_for_sql(value) # :nodoc:
|
240
|
-
value ? "'#{value.to_s}'" : 'null'
|
241
|
-
end
|
242
|
-
|
243
|
-
def value_from_sql(dbiDate, lookupLink = true) # :nodoc:
|
244
|
-
begin
|
245
|
-
dbiDate ? dbiDate.to_date : nil
|
246
|
-
rescue ArgumentError
|
247
|
-
nil
|
248
|
-
end
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
# DateTimeField represents a DateTime.
|
253
|
-
class DateTimeField < ObjectField
|
254
|
-
def value_for_sql(value) # :nodoc:
|
255
|
-
if value
|
256
|
-
year = value.year
|
257
|
-
month = value.mon.to_s.pad( 2, "0" )
|
258
|
-
day = value.day.to_s.pad( 2, "0" )
|
259
|
-
hour = value.hour.to_s.pad( 2, "0" )
|
260
|
-
minute = value.min.to_s.pad( 2, "0" )
|
261
|
-
second = value.sec.to_s.pad( 2, "0" )
|
262
|
-
"'#{year}-#{month}-#{day} #{hour}:#{minute}:#{second}'"
|
263
|
-
else
|
264
|
-
"null"
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
def value_from_sql(dbi_value, lookupLink = true) # :nodoc:
|
269
|
-
dbi_value ? dbi_value.to_time : nil
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
# DecimalField represents a decimal value.
|
274
|
-
class DecimalField < ObjectField
|
275
|
-
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
276
|
-
self.new( domain_class, parameters['name'] )
|
277
|
-
end
|
278
|
-
|
279
|
-
def self.value_type #:nodoc:
|
280
|
-
Numeric
|
281
|
-
end
|
282
|
-
|
283
|
-
def process_before_verify(value) #:nodoc:
|
284
|
-
value = super value
|
285
|
-
value != nil && value != '' ? value.to_f : nil
|
286
|
-
end
|
287
|
-
|
288
|
-
def value_from_sql(string, lookupLink = true) #:nodoc:
|
289
|
-
string != nil ? string.to_f : nil
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
# EmailField takes a text value that is expected to be formatted as a single
|
294
|
-
# valid email address.
|
295
|
-
class EmailField < TextField
|
296
|
-
# Is +address+ a valid email address?
|
297
|
-
def self.valid_address(address)
|
298
|
-
address =~ /^[^ @]+@[^ \.]+\.[^ ,]+$/
|
299
|
-
end
|
300
|
-
|
301
|
-
def initialize( domain_class, name = "email" )
|
302
|
-
super( domain_class, name )
|
303
|
-
end
|
304
|
-
|
305
|
-
def verify_non_nil(value, pk_id) #:nodoc:
|
306
|
-
super(value, pk_id)
|
307
|
-
if !EmailField.valid_address(value)
|
308
|
-
raise(
|
309
|
-
FieldValueError,
|
310
|
-
"#{ domain_class.name }##{ name } needs a valid email address.",
|
311
|
-
caller
|
312
|
-
)
|
313
|
-
end
|
314
|
-
end
|
315
|
-
end
|
316
|
-
|
317
|
-
# EnumField represents an enumerated field that can only be set to one of a
|
318
|
-
# set range of string values. To set the enumeration in the class definition
|
319
|
-
# XML, use the following format:
|
320
|
-
# <field name="flavor" class="EnumField">
|
321
|
-
# <enums>
|
322
|
-
# <enum>Vanilla</enum>
|
323
|
-
# <enum>Chocolate</enum>
|
324
|
-
# <enum>Lychee</enum>
|
325
|
-
# </enums>
|
326
|
-
# </field>
|
327
|
-
# If you're defining the field in Ruby, you can simply pass in an array of
|
328
|
-
# enums as the +enums+ argument.
|
329
|
-
#
|
330
|
-
class EnumField < TextField
|
331
|
-
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
332
|
-
self.new( domain_class, parameters['name'], parameters['enums'] )
|
333
|
-
end
|
334
|
-
|
335
|
-
def self.enum_queue_hash( fieldElt )
|
336
|
-
enumValues = []
|
337
|
-
fieldElt.elements.each( 'enums/enum' ) { |enumElt|
|
338
|
-
enumValues << enumElt.attributes['key']
|
339
|
-
enumValues << enumElt.text.to_s
|
340
|
-
}
|
341
|
-
QueueHash.new( *enumValues )
|
342
|
-
end
|
343
|
-
|
344
|
-
def self.instantiation_parameters( fieldElt ) #:nodoc:
|
345
|
-
parameters = super( fieldElt )
|
346
|
-
if fieldElt.elements['enums'][1].attributes['key']
|
347
|
-
parameters['enums'] = enum_queue_hash( fieldElt )
|
348
|
-
else
|
349
|
-
parameters['enums'] = []
|
350
|
-
fieldElt.elements.each( 'enums/enum' ) { |enumElt|
|
351
|
-
parameters['enums'] << enumElt.text.to_s
|
352
|
-
}
|
353
|
-
end
|
354
|
-
parameters
|
355
|
-
end
|
356
|
-
|
357
|
-
attr_reader :enums
|
358
|
-
|
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 )
|
365
|
-
if enums.class == Array
|
366
|
-
@enums = QueueHash.new_from_array enums
|
367
|
-
else
|
368
|
-
@enums = enums
|
369
|
-
end
|
370
|
-
end
|
371
|
-
|
372
|
-
def value_for_sql(value) #:nodoc:
|
373
|
-
value != '' ?(super(value)) : 'null'
|
374
|
-
end
|
375
|
-
|
376
|
-
def verify_non_nil( value, pk_id ) #:nodoc:
|
377
|
-
super
|
378
|
-
if @enums[value].nil?
|
379
|
-
key_str = '[ ' +
|
380
|
-
( @enums.keys.map { |key| "\"#{ key }\"" } ).join(', ') + ' ]'
|
381
|
-
err_str = "#{ @domain_class.name }##{ name } needs a value that is " +
|
382
|
-
"one of #{ key_str }"
|
383
|
-
raise( FieldValueError, err_str, caller )
|
384
|
-
end
|
385
|
-
end
|
386
|
-
end
|
387
|
-
|
388
|
-
class FieldValueError < RuntimeError #:nodoc:
|
389
|
-
end
|
390
|
-
|
391
|
-
# A LinkField is used to link from one domain class to another.
|
392
|
-
class LinkField < ObjectField
|
393
|
-
def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
|
394
|
-
instance = self.new(
|
395
|
-
domain_class, parameters['linked_type'], parameters['name'],
|
396
|
-
parameters['delete_cascade']
|
397
|
-
)
|
398
|
-
if parameters['db_field_name']
|
399
|
-
instance.db_field_name = parameters['db_field_name']
|
400
|
-
end
|
401
|
-
instance
|
402
|
-
end
|
403
|
-
|
404
|
-
def self.instantiation_parameters( fieldElt ) #:nodoc:
|
405
|
-
parameters = super( fieldElt )
|
406
|
-
linked_typeStr = fieldElt.attributes['linked_type']
|
407
|
-
linked_type = DomainObject.get_domain_class_from_string( linked_typeStr )
|
408
|
-
parameters['linked_type'] = linked_type
|
409
|
-
parameters['delete_cascade'] = fieldElt.attributes['delete_cascade'] == 'y'
|
410
|
-
parameters
|
411
|
-
end
|
412
|
-
|
413
|
-
attr_reader :linked_type
|
414
|
-
attr_accessor :delete_cascade
|
415
|
-
|
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,
|
423
|
-
delete_cascade = false )
|
424
|
-
unless name
|
425
|
-
linked_type.name =~ /::/
|
426
|
-
name = $' || linked_type.name
|
427
|
-
name = name.decapitalize
|
428
|
-
end
|
429
|
-
super( domain_class, name )
|
430
|
-
( @linked_type, @delete_cascade ) = linked_type, delete_cascade
|
431
|
-
end
|
432
|
-
|
433
|
-
def value_from_sql(string) #:nodoc:
|
434
|
-
string != nil ? DomainObjectProxy.new(@linked_type, string.to_i) : nil
|
435
|
-
end
|
436
|
-
|
437
|
-
def value_for_sql(value) #:nodoc:
|
438
|
-
if !value
|
439
|
-
"null"
|
440
|
-
elsif value.pk_id
|
441
|
-
value.pk_id
|
442
|
-
else
|
443
|
-
raise( DomainObjectInitError, "Can't commit #{name} without pk_id",
|
444
|
-
caller )
|
445
|
-
end
|
446
|
-
end
|
447
|
-
|
448
|
-
def verify_non_nil(value, pk_id) #:nodoc:
|
449
|
-
super
|
450
|
-
if @linked_type != @domain_class && pk_id
|
451
|
-
subsetLinkField = @linked_type.class_fields.find { |field|
|
452
|
-
field.class == SubsetLinkField && field.subset_field == @name
|
453
|
-
}
|
454
|
-
if subsetLinkField
|
455
|
-
verify_subset_link_field( subsetLinkField, pk_id )
|
456
|
-
end
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
|
-
def verify_subset_link_field( subsetLinkField, pk_id )
|
461
|
-
begin
|
462
|
-
prevObj = ObjectStore.get_object_store.get( domain_class, pk_id )
|
463
|
-
prevObjLinkedTo = prevObj.send(name)
|
464
|
-
possiblyMyObj = prevObjLinkedTo.send(subsetLinkField.name)
|
465
|
-
if possiblyMyObj && possiblyMyObj.pk_id == pk_id
|
466
|
-
cantChangeMsg = "You can't change that."
|
467
|
-
raise FieldValueError, cantChangeMsg, caller
|
468
|
-
end
|
469
|
-
rescue DomainObjectNotFoundError
|
470
|
-
# no previous value, so nothing to check for
|
471
|
-
end
|
472
|
-
end
|
473
|
-
end
|
474
|
-
|
475
|
-
# Accepts a Month as a value. This field automatically saves in MySQL as a
|
476
|
-
# date corresponding to the first day of the month.
|
477
|
-
class MonthField < DateField
|
478
|
-
def self.value_type #:nodoc:
|
479
|
-
Month
|
480
|
-
end
|
481
|
-
|
482
|
-
def value_for_sql(value) #:nodoc:
|
483
|
-
"'#{value.year}-#{value.month}-01'"
|
484
|
-
end
|
485
|
-
end
|
486
|
-
|
487
|
-
class PrimaryKeyField < IntegerField
|
488
|
-
def initialize( domain_class )
|
489
|
-
super( domain_class, 'pk_id' )
|
490
|
-
@not_null = false
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
# A StateField is a specialized subclass of EnumField; its possible values are
|
495
|
-
# any of the 50 states of the United States, stored as each state's two-letter
|
496
|
-
# postal code.
|
497
|
-
class StateField < EnumField
|
498
|
-
def initialize( domain_class, name = "state" )
|
499
|
-
super( domain_class, name, UsStates.states )
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
class SubsetLinkField < LinkField #:nodoc:
|
504
|
-
def self.instantiate_with_parameters( domain_class, parameters )
|
505
|
-
self.new( domain_class, parameters['linked_type'],
|
506
|
-
parameters['subset_field'], parameters['name'] )
|
507
|
-
end
|
508
|
-
|
509
|
-
def self.instantiation_parameters( fieldElt )
|
510
|
-
parameters = super( fieldElt )
|
511
|
-
parameters['subset_field'] = fieldElt.attributes['subset_field']
|
512
|
-
parameters
|
513
|
-
end
|
514
|
-
|
515
|
-
attr_accessor :subset_field
|
516
|
-
|
517
|
-
def initialize( domain_class, linked_type, subset_field,
|
518
|
-
name = linked_type.name.downcase )
|
519
|
-
super( domain_class, linked_type, name )
|
520
|
-
@subset_field = subset_field
|
521
|
-
end
|
522
|
-
end
|
523
|
-
|
524
|
-
# TextListField maps to any String SQL field that tries to represent a
|
525
|
-
# quick-and-dirty list with a comma-separated string. It returns an Array.
|
526
|
-
# For example, a SQL field with the value "john,bill,dave", then the Ruby
|
527
|
-
# field will have the value <tt>[ "john", "bill", "dave" ]</tt>.
|
528
|
-
class TextListField < ObjectField
|
529
|
-
def self.value_type #:nodoc:
|
530
|
-
Array
|
531
|
-
end
|
532
|
-
|
533
|
-
def value_for_sql(objectValue) #:nodoc:
|
534
|
-
if objectValue.is_a?( Array )
|
535
|
-
str = objectValue.join(',')
|
536
|
-
else
|
537
|
-
str = objectValue
|
538
|
-
end
|
539
|
-
"'" + str + "'"
|
540
|
-
end
|
541
|
-
|
542
|
-
def value_from_sql(sqlString, lookupLink = true) #:nodoc:
|
543
|
-
if sqlString
|
544
|
-
sqlString.split ','
|
545
|
-
else
|
546
|
-
[]
|
547
|
-
end
|
548
|
-
end
|
549
|
-
end
|
550
|
-
|
551
|
-
class TimeStampField < DateTimeField #:nodoc:
|
552
|
-
def initialize( domain_class, name = 'timeStamp' )
|
553
|
-
super( domain_class, name )
|
554
|
-
@not_null = false
|
555
|
-
end
|
556
|
-
|
557
|
-
def db_will_automatically_write
|
558
|
-
true
|
559
|
-
end
|
560
|
-
end
|
561
|
-
end
|