lafcadio 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,16 +0,0 @@
1
- dir = Dir.new 'lafcadio/'
2
- dir.each { |entry|
3
- if ![ '.', '..', 'CVS' ].index(entry) && entry !~ /~$/
4
- begin
5
- subDirName = entry
6
- subDir = Dir.new "lafcadio/#{ subDirName }"
7
- subDir.each { |entry|
8
- if entry =~ /.rb$/
9
- require "lafcadio/#{subDirName}/#{entry}"
10
- end
11
- }
12
- rescue StandardError
13
- # not a directory, whatev
14
- end
15
- end
16
- }
@@ -1,93 +0,0 @@
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.
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( month = nil, year = 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( resultMonth, resultYear )
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
@@ -1,93 +0,0 @@
1
- require 'lafcadio/objectStore'
2
-
3
- module Lafcadio
4
- class MockDbBridge #:nodoc:
5
- attr_reader :last_pk_id_inserted, :retrievals_by_type, :query_count
6
-
7
- def initialize
8
- @objects = {}
9
- @retrievals_by_type = Hash.new 0
10
- @query_count = Hash.new( 0 )
11
- end
12
-
13
- def commit(db_object)
14
- objectsByObjectType = get_objects_by_domain_class( db_object.object_type )
15
- if db_object.delete
16
- objectsByObjectType.delete db_object.pk_id
17
- else
18
- object_pk_id = get_pk_id_before_committing( db_object )
19
- objectsByObjectType[object_pk_id] = db_object
20
- end
21
- end
22
-
23
- def _get_all(object_type)
24
- @retrievals_by_type[object_type] = @retrievals_by_type[object_type] + 1
25
- @objects[object_type] ? @objects[object_type].values : []
26
- end
27
-
28
- def get_collection_by_query(query)
29
- @query_count[query] += 1
30
- objects = []
31
- _get_all( query.object_type ).each { |dbObj|
32
- if query.condition
33
- objects << dbObj if query.condition.object_meets(dbObj)
34
- else
35
- objects << dbObj
36
- end
37
- }
38
- if (range = query.limit)
39
- objects = objects[0..(range.last - range.first)]
40
- end
41
- if ( order_by = query.order_by )
42
- objects = objects.sort_by { |dobj| dobj.send( order_by ) }
43
- objects.reverse! if query.order_by_order == Query::DESC
44
- end
45
- objects
46
- end
47
-
48
- def get_pk_id_before_committing( db_object )
49
- object_pk_id = db_object.pk_id
50
- unless object_pk_id
51
- maxpk_id = 0
52
- get_objects_by_domain_class( db_object.object_type ).keys.each { |pk_id|
53
- maxpk_id = pk_id if pk_id > maxpk_id
54
- }
55
- @last_pk_id_inserted = maxpk_id + 1
56
- object_pk_id = @last_pk_id_inserted
57
- end
58
- object_pk_id
59
- end
60
-
61
- def get_objects_by_domain_class( domain_class )
62
- objects_by_domain_class = @objects[domain_class]
63
- unless objects_by_domain_class
64
- objects_by_domain_class = {}
65
- @objects[domain_class] = objects_by_domain_class
66
- end
67
- objects_by_domain_class
68
- end
69
-
70
- def group_query( query )
71
- if query.class == Query::Max
72
- if ( query.field_name == query.object_type.sql_primary_key_name ||
73
- query.field_name == 'rate' )
74
- query.collect( @objects[query.object_type].values )
75
- else
76
- raise "Can't handle query with sql '#{ query.to_sql }'"
77
- end
78
- end
79
- end
80
- end
81
-
82
- # Externally, the MockObjectStore looks and acts exactly like the ObjectStore,
83
- # but stores all its data in memory. This makes it very useful for unit
84
- # testing, and in fact LafcadioTestCase#setup creates a new instance of
85
- # MockObjectStore for each test case.
86
- class MockObjectStore < ObjectStore
87
- public_class_method :new
88
-
89
- def initialize # :nodoc:
90
- super( MockDbBridge.new )
91
- end
92
- end
93
- end
@@ -1,618 +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, :object_type
11
- attr_accessor :not_null, :unique, :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
- parameters['english_name'] )
21
- if ( db_field_name = parameters['db_field_name'] )
22
- instance.db_field_name = db_field_name
23
- end
24
- instance
25
- end
26
-
27
- def self.instantiation_parameters( fieldElt ) #:nodoc:
28
- parameters = {}
29
- parameters['name'] = fieldElt.attributes['name']
30
- parameters['english_name'] = fieldElt.attributes['english_name']
31
- parameters['db_field_name'] = fieldElt.attributes['db_field_name']
32
- parameters
33
- end
34
-
35
- def self.value_type #:nodoc:
36
- Object
37
- end
38
-
39
- # [object_type] The domain class that this object field belongs to.
40
- # [name] The name of this field.
41
- # [english_name] The descriptive English name of this field. (Deprecated)
42
- def initialize(object_type, name, english_name = nil )
43
- @object_type = object_type
44
- @name = name
45
- @db_field_name = name
46
- @not_null = true
47
- @unique = false
48
- @english_nameOrNil = english_name
49
- end
50
-
51
- def <=>(other)
52
- if @object_type == other.object_type && name == other.name
53
- 0
54
- else
55
- object_id <=> other.object_id
56
- end
57
- end
58
-
59
- def bind_write?; false; end #:nodoc:
60
-
61
- def db_table_and_field_name
62
- "#{ object_type.table_name }.#{ db_field_name }"
63
- end
64
-
65
- def db_will_automatically_write #:nodoc:
66
- false
67
- end
68
-
69
- def english_name #:nodoc:
70
- @english_nameOrNil || English.camel_case_to_english(name).capitalize
71
- end
72
-
73
- # Returns the name that this field is referenced by in the MySQL table. By
74
- # default this is the same as the name; to override it, set
75
- # ObjectField#db_field_name.
76
- def name_for_sql
77
- db_field_name
78
- end
79
-
80
- def null_error_msg #:nodoc:
81
- "#{ self.object_type.name }##{ name } can not be nil."
82
- end
83
-
84
- def prev_value(pk_id) #:nodoc:
85
- prevObject = ObjectStore.get_object_store.get(@object_type, pk_id)
86
- prevObject.send(name)
87
- end
88
-
89
- def process_before_verify(value) #:nodoc:
90
- value = @default if value == nil
91
- value
92
- end
93
-
94
- # Returns a string value suitable for committing this field's value to
95
- # MySQL.
96
- def value_for_sql(value)
97
- value || 'null'
98
- end
99
-
100
- def verify(value, pk_id) #:nodoc:
101
- if value.nil? && not_null
102
- raise FieldValueError, null_error_msg, caller
103
- end
104
- verify_non_nil( value, pk_id ) if value
105
- end
106
-
107
- def verify_non_nil( value, pk_id )
108
- value_type = self.class.value_type
109
- unless value.class <= value_type
110
- raise( FieldValueError,
111
- "#{ object_type.name }##{ name } needs a " + value_type.name +
112
- " value.",
113
- caller )
114
- end
115
- verify_uniqueness(value, pk_id) if unique
116
- end
117
-
118
- def verify_uniqueness(value, pk_id) #:nodoc:
119
- inferrer = Query::Inferrer.new( @object_type ) { |domain_obj|
120
- Query.And( domain_obj.send( self.name ).equals( value ),
121
- domain_obj.pk_id.equals( pk_id ).not )
122
- }
123
- collisions = ObjectStore.get_object_store.get_subset( inferrer.execute )
124
- if collisions.size > 0
125
- notUniqueMsg = "That #{english_name.downcase} already exists."
126
- raise FieldValueError, notUniqueMsg, caller
127
- end
128
- end
129
-
130
- # Given the SQL value string, returns a Ruby-native value.
131
- def value_from_sql(string)
132
- string
133
- end
134
- end
135
-
136
- # IntegerField represents an integer.
137
- class IntegerField < ObjectField
138
- def value_from_sql(string) #:nodoc:
139
- value = super
140
- value ? value.to_i : nil
141
- end
142
- end
143
-
144
- # A TextField is expected to contain a string value.
145
- class TextField < ObjectField
146
- def value_for_sql(value) #:nodoc:
147
- if value
148
- value = value.gsub(/(\\?')/) { |m| m.length == 1 ? "''" : m }
149
- value = value.gsub(/\\/) { '\\\\' }
150
- "'#{value}'"
151
- else
152
- "null"
153
- end
154
- end
155
- end
156
-
157
- class AutoIncrementField < IntegerField # :nodoc:
158
- attr_reader :object_type
159
-
160
- def initialize(object_type, name, english_name = nil)
161
- super(object_type, name, english_name)
162
- @object_type = object_type
163
- end
164
-
165
- def html_widget_value_str(value)
166
- if value != nil
167
- super value
168
- else
169
- highestValue = 0
170
- ObjectStore.get_object_store.get_all(object_type).each { |obj|
171
- aValue = obj.send(name).to_i
172
- highestValue = aValue if aValue > highestValue
173
- }
174
- (highestValue + 1).to_s
175
- end
176
- end
177
- end
178
-
179
- # BlobField stores a string value and expects to store its value in a BLOB
180
- # field in the database.
181
- class BlobField < ObjectField
182
- attr_accessor :size
183
-
184
- def self.value_type; String; end
185
-
186
- def bind_write?; true; end #:nodoc:
187
-
188
- def value_for_sql(value); "?"; end #:nodoc:
189
- end
190
-
191
- # BooleanField represents a boolean value. By default, it assumes that the
192
- # table field represents True and False with the integers 1 and 0. There are
193
- # two different ways to change this default.
194
- #
195
- # First, BooleanField includes a few enumerated defaults. Currently there are
196
- # only
197
- # * BooleanField::ENUMS_ONE_ZERO (the default, uses integers 1 and 0)
198
- # * BooleanField::ENUMS_CAPITAL_YES_NO (uses characters 'Y' and 'N')
199
- # In the XML class definition, this field would look like
200
- # <field name="field_name" class="BooleanField"
201
- # enum_type="ENUMS_CAPITAL_YES_NO"/>
202
- # If you're defining a field in Ruby, simply set BooleanField#enum_type to one
203
- # of the values.
204
- #
205
- # For more fine-grained specification you can pass specific values in. Use
206
- # this format for the XML class definition:
207
- # <field name="field_name" class="BooleanField">
208
- # <enums>
209
- # <enum key="true">yin</enum>
210
- # <enum key="false">tang</enum>
211
- # </enums>
212
- # </field>
213
- # If you're defining the field in Ruby, set BooleanField#enums to a hash.
214
- # myBooleanField.enums = { true => 'yin', false => 'yang' }
215
- #
216
- # +enums+ takes precedence over +enum_type+.
217
- class BooleanField < ObjectField
218
- ENUMS_ONE_ZERO = 0
219
- ENUMS_CAPITAL_YES_NO = 1
220
-
221
- attr_accessor :enum_type, :enums
222
-
223
- def initialize(object_type, name, english_name = nil)
224
- super(object_type, name, english_name)
225
- @enum_type = ENUMS_ONE_ZERO
226
- @enums = nil
227
- end
228
-
229
- def false_enum # :nodoc:
230
- get_enums[false]
231
- end
232
-
233
- def get_enums( value = nil ) # :nodoc:
234
- if @enums
235
- @enums
236
- elsif @enum_type == ENUMS_ONE_ZERO
237
- if value.class == String
238
- { true => '1', false => '0' }
239
- else
240
- { true => 1, false => 0 }
241
- end
242
- elsif @enum_type == ENUMS_CAPITAL_YES_NO
243
- { true => 'Y', false => 'N' }
244
- else
245
- raise MissingError
246
- end
247
- end
248
-
249
- def text_enum_type # :nodoc:
250
- @enums ? @enums[true].class == String : @enum_type == ENUMS_CAPITAL_YES_NO
251
- end
252
-
253
- def true_enum( value = nil ) # :nodoc:
254
- get_enums( value )[true]
255
- end
256
-
257
- def value_for_sql(value) # :nodoc:
258
- if value
259
- vfs = true_enum
260
- else
261
- vfs = false_enum
262
- end
263
- text_enum_type ? "'#{vfs}'" : vfs
264
- end
265
-
266
- def value_from_sql(value, lookupLink = true) # :nodoc:
267
- value == true_enum( value )
268
- end
269
- end
270
-
271
- # DateField represents a Date.
272
- class DateField < ObjectField
273
- RANGE_NEAR_FUTURE = 0
274
- RANGE_PAST = 1
275
-
276
- def self.value_type # :nodoc:
277
- Date
278
- end
279
-
280
- attr_accessor :range
281
-
282
- def initialize(object_type, name = "date", english_name = nil)
283
- super(object_type, name, english_name)
284
- @range = RANGE_NEAR_FUTURE
285
- end
286
-
287
- def value_for_sql(value) # :nodoc:
288
- value ? "'#{value.to_s}'" : 'null'
289
- end
290
-
291
- def value_from_sql(dbiDate, lookupLink = true) # :nodoc:
292
- begin
293
- dbiDate ? dbiDate.to_date : nil
294
- rescue ArgumentError
295
- nil
296
- end
297
- end
298
- end
299
-
300
- # DateTimeField represents a DateTime.
301
- class DateTimeField < ObjectField
302
- def value_for_sql(value) # :nodoc:
303
- if value
304
- year = value.year
305
- month = value.mon.to_s.pad( 2, "0" )
306
- day = value.day.to_s.pad( 2, "0" )
307
- hour = value.hour.to_s.pad( 2, "0" )
308
- minute = value.min.to_s.pad( 2, "0" )
309
- second = value.sec.to_s.pad( 2, "0" )
310
- "'#{year}-#{month}-#{day} #{hour}:#{minute}:#{second}'"
311
- else
312
- "null"
313
- end
314
- end
315
-
316
- def value_from_sql(dbi_value, lookupLink = true) # :nodoc:
317
- dbi_value ? dbi_value.to_time : nil
318
- end
319
- end
320
-
321
- # DecimalField represents a decimal value.
322
- class DecimalField < ObjectField
323
- def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
324
- self.new( domain_class, parameters['name'], parameters['english_name'] )
325
- end
326
-
327
- def self.value_type #:nodoc:
328
- Numeric
329
- end
330
-
331
- def process_before_verify(value) #:nodoc:
332
- value = super value
333
- value != nil && value != '' ? value.to_f : nil
334
- end
335
-
336
- def value_from_sql(string, lookupLink = true) #:nodoc:
337
- string != nil ? string.to_f : nil
338
- end
339
- end
340
-
341
- # EmailField takes a text value that is expected to be formatted as a single
342
- # valid email address.
343
- class EmailField < TextField
344
- # Is +address+ a valid email address?
345
- def self.valid_address(address)
346
- address =~ /^[^ @]+@[^ \.]+\.[^ ,]+$/
347
- end
348
-
349
- def initialize(object_type, name = "email", english_name = nil)
350
- super(object_type, name, english_name)
351
- end
352
-
353
- def null_error_msg #:nodoc:
354
- "Please enter an email address."
355
- end
356
-
357
- def verify_non_nil(value, pk_id) #:nodoc:
358
- super(value, pk_id)
359
- if !EmailField.valid_address(value)
360
- raise( FieldValueError,
361
- "#{ object_type.name }##{ name } needs a valid email address.",
362
- caller )
363
- end
364
- end
365
- end
366
-
367
- # EnumField represents an enumerated field that can only be set to one of a
368
- # set range of string values. To set the enumeration in the class definition
369
- # XML, use the following format:
370
- # <field name="flavor" class="EnumField">
371
- # <enums>
372
- # <enum>Vanilla</enum>
373
- # <enum>Chocolate</enum>
374
- # <enum>Lychee</enum>
375
- # </enums>
376
- # </field>
377
- # If you're defining the field in Ruby, you can simply pass in an array of
378
- # enums as the +enums+ argument.
379
- #
380
- class EnumField < TextField
381
- def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
382
- self.new( domain_class, parameters['name'], parameters['enums'],
383
- parameters['english_name'] )
384
- end
385
-
386
- def self.enum_queue_hash( fieldElt )
387
- enumValues = []
388
- fieldElt.elements.each( 'enums/enum' ) { |enumElt|
389
- enumValues << enumElt.attributes['key']
390
- enumValues << enumElt.text.to_s
391
- }
392
- QueueHash.new( *enumValues )
393
- end
394
-
395
- def self.instantiation_parameters( fieldElt ) #:nodoc:
396
- parameters = super( fieldElt )
397
- if fieldElt.elements['enums'][1].attributes['key']
398
- parameters['enums'] = enum_queue_hash( fieldElt )
399
- else
400
- parameters['enums'] = []
401
- fieldElt.elements.each( 'enums/enum' ) { |enumElt|
402
- parameters['enums'] << enumElt.text.to_s
403
- }
404
- end
405
- parameters
406
- end
407
-
408
- attr_reader :enums
409
-
410
- # [object_type] The domain class that this field belongs to.
411
- # [name] The name of this domain class.
412
- # [enums] An array of Strings representing the possible choices for
413
- # this field.
414
- # [english_name] The English name of this field. (Deprecated)
415
- def initialize(object_type, name, enums, english_name = nil)
416
- super object_type, name, english_name
417
- if enums.class == Array
418
- @enums = QueueHash.new_from_array enums
419
- else
420
- @enums = enums
421
- end
422
- end
423
-
424
- def value_for_sql(value) #:nodoc:
425
- value != '' ?(super(value)) : 'null'
426
- end
427
-
428
- def verify_non_nil( value, pk_id ) #:nodoc:
429
- super
430
- if @enums[value].nil?
431
- key_str = '[ ' +
432
- ( @enums.keys.map { |key| "\"#{ key }\"" } ).join(', ') + ' ]'
433
- err_str = "#{ @object_type.name }##{ name } needs a value that is " +
434
- "one of #{ key_str }"
435
- raise( FieldValueError, err_str, caller )
436
- end
437
- end
438
- end
439
-
440
- class FieldValueError < RuntimeError #:nodoc:
441
- end
442
-
443
- # A LinkField is used to link from one domain class to another.
444
- class LinkField < ObjectField
445
- def self.instantiate_with_parameters( domain_class, parameters ) #:nodoc:
446
- instance = self.new(
447
- domain_class, parameters['linked_type'], parameters['name'],
448
- parameters['english_name'], parameters['delete_cascade']
449
- )
450
- if parameters['db_field_name']
451
- instance.db_field_name = parameters['db_field_name']
452
- end
453
- instance
454
- end
455
-
456
- def self.instantiation_parameters( fieldElt ) #:nodoc:
457
- parameters = super( fieldElt )
458
- linked_typeStr = fieldElt.attributes['linked_type']
459
- linked_type = DomainObject.get_object_type_from_string( linked_typeStr )
460
- parameters['linked_type'] = linked_type
461
- parameters['delete_cascade'] = fieldElt.attributes['delete_cascade'] == 'y'
462
- parameters
463
- end
464
-
465
- attr_reader :linked_type
466
- attr_accessor :delete_cascade
467
-
468
- # [object_type] The domain class that this field belongs to.
469
- # [linked_type] The domain class that this field points to.
470
- # [name] The name of this field.
471
- # [english_name] The English name of this field. (Deprecated)
472
- # [delete_cascade] If this is true, deleting the domain object that is linked
473
- # to will cause this domain object to be deleted as well.
474
- def initialize( object_type, linked_type, name = nil, english_name = nil,
475
- delete_cascade = false )
476
- unless name
477
- linked_type.name =~ /::/
478
- name = $' || linked_type.name
479
- name = name.decapitalize
480
- end
481
- super(object_type, name, english_name)
482
- ( @linked_type, @delete_cascade ) = linked_type, delete_cascade
483
- end
484
-
485
- def value_from_sql(string) #:nodoc:
486
- string != nil ? DomainObjectProxy.new(@linked_type, string.to_i) : nil
487
- end
488
-
489
- def value_for_sql(value) #:nodoc:
490
- if !value
491
- "null"
492
- elsif value.pk_id
493
- value.pk_id
494
- else
495
- raise( DomainObjectInitError, "Can't commit #{name} without pk_id",
496
- caller )
497
- end
498
- end
499
-
500
- def verify_non_nil(value, pk_id) #:nodoc:
501
- super
502
- if @linked_type != @object_type && pk_id
503
- subsetLinkField = @linked_type.class_fields.find { |field|
504
- field.class == SubsetLinkField && field.subset_field == @name
505
- }
506
- if subsetLinkField
507
- verify_subset_link_field( subsetLinkField, pk_id )
508
- end
509
- end
510
- end
511
-
512
- def verify_subset_link_field( subsetLinkField, pk_id )
513
- begin
514
- prevObj = ObjectStore.get_object_store.get(object_type, pk_id)
515
- prevObjLinkedTo = prevObj.send(name)
516
- possiblyMyObj = prevObjLinkedTo.send(subsetLinkField.name)
517
- if possiblyMyObj && possiblyMyObj.pk_id == pk_id
518
- cantChangeMsg = "You can't change that."
519
- raise FieldValueError, cantChangeMsg, caller
520
- end
521
- rescue DomainObjectNotFoundError
522
- # no previous value, so nothing to check for
523
- end
524
- end
525
- end
526
-
527
- class MoneyField < DecimalField #:nodoc:
528
- end
529
-
530
- # Accepts a Month as a value. This field automatically saves in MySQL as a
531
- # date corresponding to the first day of the month.
532
- class MonthField < DateField
533
- def self.value_type #:nodoc:
534
- Month
535
- end
536
-
537
- def value_for_sql(value) #:nodoc:
538
- "'#{value.year}-#{value.month}-01'"
539
- end
540
- end
541
-
542
- # A PasswordField is simply a TextField that is expected to contain a password
543
- # value. It can be set to auto-generate a password at random.
544
- class PasswordField < TextField
545
- # Returns a random 8-letter alphanumeric password.
546
- def self.random_password
547
- chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".
548
- split(//)
549
- value = ""
550
- 0.upto(8) { |i| value += chars[rand(chars.size)] }
551
- value
552
- end
553
- end
554
-
555
- # A StateField is a specialized subclass of EnumField; its possible values are
556
- # any of the 50 states of the United States, stored as each state's two-letter
557
- # postal code.
558
- class StateField < EnumField
559
- def initialize(object_type, name = "state", english_name = nil)
560
- super object_type, name, UsStates.states, english_name
561
- end
562
- end
563
-
564
- class SubsetLinkField < LinkField #:nodoc:
565
- def self.instantiate_with_parameters( domain_class, parameters )
566
- self.new( domain_class, parameters['linked_type'],
567
- parameters['subset_field'], parameters['name'],
568
- parameters['english_name'] )
569
- end
570
-
571
- def self.instantiation_parameters( fieldElt )
572
- parameters = super( fieldElt )
573
- parameters['subset_field'] = fieldElt.attributes['subset_field']
574
- parameters
575
- end
576
-
577
- attr_accessor :subset_field
578
-
579
- def initialize(object_type, linked_type, subset_field,
580
- name = linked_type.name.downcase, english_name = nil)
581
- super(object_type, linked_type, name, english_name)
582
- @subset_field = subset_field
583
- end
584
- end
585
-
586
- # TextListField maps to any String SQL field that tries to represent a
587
- # quick-and-dirty list with a comma-separated string. It returns an Array.
588
- # For example, a SQL field with the value "john,bill,dave", then the Ruby
589
- # field will have the value <tt>[ "john", "bill", "dave" ]</tt>.
590
- class TextListField < ObjectField
591
- def self.value_type #:nodoc:
592
- Array
593
- end
594
-
595
- def value_for_sql(objectValue) #:nodoc:
596
- "'" + objectValue.join(',') + "'"
597
- end
598
-
599
- def value_from_sql(sqlString, lookupLink = true) #:nodoc:
600
- if sqlString
601
- sqlString.split ','
602
- else
603
- []
604
- end
605
- end
606
- end
607
-
608
- class TimeStampField < DateTimeField #:nodoc:
609
- def initialize(object_type, name = 'timeStamp', english_name = nil)
610
- super( object_type, name, english_name )
611
- @not_null = false
612
- end
613
-
614
- def db_will_automatically_write
615
- true
616
- end
617
- end
618
- end