gedcom 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gemtest +0 -0
  2. data/History.txt +8 -2
  3. data/Manifest.txt +4 -0
  4. data/README.txt +1 -1
  5. data/Rakefile +13 -5
  6. data/lib/gedcom.rb +3 -1
  7. data/lib/gedcom/address_record.rb +0 -0
  8. data/lib/gedcom/adoption_record.rb +0 -0
  9. data/lib/gedcom/association_record.rb +3 -3
  10. data/lib/gedcom/cause_record.rb +0 -0
  11. data/lib/gedcom/change_date_record.rb +0 -0
  12. data/lib/gedcom/character_set_record.rb +0 -0
  13. data/lib/gedcom/citation_data_record.rb +0 -0
  14. data/lib/gedcom/citation_event_type_record.rb +0 -0
  15. data/lib/gedcom/corporate_record.rb +0 -0
  16. data/lib/gedcom/date_record.rb +18 -0
  17. data/lib/gedcom/encoded_line_record.rb +0 -0
  18. data/lib/gedcom/event_age_record.rb +0 -0
  19. data/lib/gedcom/event_record.rb +13 -3
  20. data/lib/gedcom/events_list_record.rb +0 -0
  21. data/lib/gedcom/families_individuals.rb +2 -2
  22. data/lib/gedcom/family_record.rb +165 -3
  23. data/lib/gedcom/ged_string.rb +49 -0
  24. data/lib/gedcom/gedcom_all.rb +2 -0
  25. data/lib/gedcom/gedcom_base.rb +45 -15
  26. data/lib/gedcom/gedcom_record.rb +0 -0
  27. data/lib/gedcom/header_data_record.rb +0 -0
  28. data/lib/gedcom/header_record.rb +0 -0
  29. data/lib/gedcom/header_source_record.rb +0 -0
  30. data/lib/gedcom/individual_attribute_record.rb +25 -2
  31. data/lib/gedcom/individual_record.rb +436 -13
  32. data/lib/gedcom/multimedia_citation_record.rb +0 -0
  33. data/lib/gedcom/multimedia_record.rb +0 -0
  34. data/lib/gedcom/name_record.rb +70 -0
  35. data/lib/gedcom/note_citation_record.rb +0 -0
  36. data/lib/gedcom/note_record.rb +0 -0
  37. data/lib/gedcom/place_record.rb +6 -0
  38. data/lib/gedcom/refn_record.rb +0 -0
  39. data/lib/gedcom/repository_caln.rb +0 -0
  40. data/lib/gedcom/repository_citation_record.rb +0 -0
  41. data/lib/gedcom/repository_record.rb +0 -0
  42. data/lib/gedcom/source_citation_record.rb +0 -0
  43. data/lib/gedcom/source_record.rb +0 -0
  44. data/lib/gedcom/source_scope_record.rb +0 -0
  45. data/lib/gedcom/submission_record.rb +0 -0
  46. data/lib/gedcom/submitter_record.rb +0 -0
  47. data/lib/gedcom/text_record.rb +0 -0
  48. data/lib/gedcom/trailer_record.rb +0 -0
  49. data/lib/gedcom/transmission.rb +9 -0
  50. data/lib/gedcom/transmission_base.rb +81 -37
  51. data/lib/gedcom/xref.rb +8 -0
  52. data/lib/parser/class_tracker.rb +0 -0
  53. data/lib/parser/ged_line.rb +0 -0
  54. data/lib/parser/gedcom_parser.rb +0 -0
  55. data/lib/parser/instruction.rb +0 -0
  56. data/lib/parser/parse_state.rb +0 -0
  57. data/test/lds_gedcom_test.rb +61 -0
  58. data/test/ruby_version.rb +43 -0
  59. data/test/test_gedcom.rb +0 -0
  60. metadata +57 -16
@@ -39,3 +39,5 @@ require 'submitter_record.rb'
39
39
  require 'text_record.rb'
40
40
  require 'trailer_record.rb'
41
41
  require 'transmission_base.rb'
42
+ require 'xref.rb'
43
+ require 'ged_string.rb'
@@ -3,7 +3,9 @@ require "instruction.rb"
3
3
 
4
4
  #base routines shared by all gedcom objects.
5
5
  class GEDCOMBase
6
- attr_accessor :class_stack, :indexes
6
+ #Restriction records only exist in some GEDCOM record types, and we do honor that.
7
+ #Internally though, my DB allows any record to be restricted, hence this global use of :restriction.
8
+ attr_accessor :restriction
7
9
  @@tabs = false #If true, indent gedcom lines on output a tab per level. Normally wouldn't have tabs in a transmission file.
8
10
 
9
11
  #Create a new GEDCOMBase or most likely a subclass of GEDCOMBase.
@@ -54,10 +56,12 @@ class GEDCOMBase
54
56
  #create a string from the objects instance variables, one per line, in the form "variable = value\n" ... .
55
57
  #For an ordered list, see to_s_ordered
56
58
  def to_s
59
+ #This might seem a little obscure, but this will find and print the attributes with get methods defined,
60
+ #not having prior knowledge of what those attributes are.
57
61
  s = ''
58
62
  self.instance_variables.each do |v| #look at each of the instance variables
59
63
  if self.class.method_defined?(v_sym = v[1..-1].to_sym) #see if there is a method defined for this symbol (strip the :)
60
- s += "#{v} = " + pv_byname(v_sym) + "\n" #print it
64
+ s += "#{v} = " + pv_byname(v_sym).to_s + "\n" #print it
61
65
  end
62
66
  end
63
67
  s
@@ -83,6 +87,30 @@ class GEDCOMBase
83
87
  to_db( level, @this_level, @sub_level)
84
88
  end
85
89
 
90
+ #Find a XREF within this transmission. All classes inheriting from GEDCOMBase record the parent transmission object.
91
+ def find(*a)
92
+ @transmission.find(*a) if @transmission != nil
93
+ end
94
+
95
+ #Test for a Restriction notice for privacy
96
+ #People may request that a records contents not be available for public consumption.
97
+ def private?
98
+ (@restriction != nil && @restriction == "privacy") ? true : false
99
+ end
100
+
101
+ #Test for a Restriction notice for a locked record.
102
+ #Locked records mean that the data is known to be correct, so shouldn't be
103
+ #altered without checking with the original source of the data.
104
+ def locked?
105
+ (@restriction != nil && @restriction == "locked") ? true : false
106
+ end
107
+
108
+ #All our values are stored as arrays of words. This is quite useful in word wrapping of NOTES, TEXT, etc, and further parsing records like dates.
109
+ #It isn't really that helpful when we want to use a value as a string. This is a utility function to join the words into a space separated string.
110
+ def token_to_s(token)
111
+ token
112
+ end
113
+
86
114
  private
87
115
 
88
116
  #Somewhat cryptic. This takes the symbol (variable name) and returns the object associatied with it.
@@ -125,7 +153,7 @@ class GEDCOMBase
125
153
  #printing aid for tags that can have CONT or CONC sub-tags
126
154
  s_out = "#{tabstop(level)}#{level} #{tag}"
127
155
  if data != nil
128
- data.each do |word|
156
+ data.each_word do |word|
129
157
  if word != "\n"
130
158
  s_out += " #{word}"
131
159
  end
@@ -156,10 +184,10 @@ class GEDCOMBase
156
184
  #printing aid for tags that can have CONT or CONC sub-tags
157
185
  s_out = "#{tabstop(level)}#{level} #{tag}"
158
186
  nlevel = level + (conc ? 0 : 1)
159
-
187
+
160
188
  if data != nil
161
189
  length = s_out.length
162
- data.each_with_index do |word,i|
190
+ data.each_word_with_index do |word,i|
163
191
  if length > 253 && word != "\n" && data.length != i #253 allows for CR LF or LF CR pairs as the line terminator.
164
192
  s_tmp = "#{tabstop(nlevel)}#{nlevel} CONC"
165
193
  length = s_tmp.length #new line, so reset length
@@ -188,7 +216,7 @@ class GEDCOMBase
188
216
  s_out = "#{tabstop(level)}#{level} CONT"
189
217
 
190
218
  if data != nil
191
- data.each_with_index do |word,i|
219
+ data.each_word_with_index do |word,i|
192
220
  s_out += " #{word}"
193
221
  if word == "\n"
194
222
  s_out += "#{tabstop(level)}#{level} CONT"
@@ -203,9 +231,9 @@ class GEDCOMBase
203
231
  #Level n GEDCOM records have the @XREF@ after the tag.
204
232
  def xref(level, tag, xref)
205
233
  if level == 0
206
- "#{tabstop(level)}#{level} @#{xref}@ #{tag}\n"
234
+ "#{tabstop(level)}#{level} @#{xref.xref_value}@ #{tag}\n"
207
235
  else
208
- "#{tabstop(level)}#{level} #{tag} @#{xref}@\n"
236
+ "#{tabstop(level)}#{level} #{tag} @#{xref.xref_value}@\n"
209
237
  end
210
238
  end
211
239
 
@@ -229,8 +257,8 @@ class GEDCOMBase
229
257
  def to_s_r_action(level, action, tag, data=nil)
230
258
  case action
231
259
  when :xref then
232
- xref_check(level, tag, data[0], data[1])
233
- xref(level, tag, data[1])
260
+ xref_check(level, tag, data)
261
+ xref(level, tag, data)
234
262
  when :print then single_line(level, tag, data )
235
263
  when :conc then cont_conc(level, tag, true, data )
236
264
  when :cont then cont_conc(level, tag, false, data )
@@ -246,10 +274,10 @@ class GEDCOMBase
246
274
 
247
275
  #validate that the record referenced by the XREF actually exists in this transmission.
248
276
  #Genearte a warning if it does not. It does not stop the processing of this line.
249
- def xref_check(level, tag, index, xref)
250
- if @transmission != nil && @transmission.find(index, xref) == nil
277
+ def xref_check( level, tag, xref )
278
+ if @transmission != nil && @transmission.find(xref.index, xref.xref_value) == nil
251
279
  #Warning message that reference points to an unknown target.
252
- print "#{level+1} NOTE ****************Key not found: #{index} #{xref}\n"
280
+ print "#{level+1} NOTE ****************#{level}, #{tag} Key not found: #{xref.index} #{xref.xref_value}\n"
253
281
  end
254
282
  end
255
283
 
@@ -277,8 +305,9 @@ class GEDCOMBase
277
305
  if this_level_instruction.data != nil
278
306
  data = self.send( this_level_instruction.data ) #gets the contents using the symbol, and sending "self" a message
279
307
  else
280
- data = [['']]
308
+ data = [GedString.new('')]
281
309
  end
310
+
282
311
  if data != nil #could be if the self.send targets a variable that doesn't exist.
283
312
  data.each do |data_instance|
284
313
  s_out += to_s_r_action(level, this_level_instruction.action, this_level_instruction.tag, data_instance)
@@ -288,8 +317,9 @@ class GEDCOMBase
288
317
  if sub_level_instruction.data != nil
289
318
  sub_level_data = self.send( sub_level_instruction.data ) #gets the contents using the symbol, and sending "self" a message
290
319
  else
291
- sub_level_data = [['']]
320
+ sub_level_data = [GedString.new('')]
292
321
  end
322
+
293
323
  if sub_level_data != nil #could be if the self.send targets a variable that doesn't exist.
294
324
  sub_level_data.each do |sub_data_instance|
295
325
  s_out += to_s_r_action(level+1, sub_level_instruction.action, sub_level_instruction.tag, sub_data_instance )
File without changes
File without changes
File without changes
File without changes
@@ -51,19 +51,42 @@ class Individual_attribute_record < Event_record
51
51
 
52
52
  ClassTracker << :Individual_attribute_record
53
53
 
54
+ #attr_type= stores the attribute type in the event_type field.
55
+ #this minor hack lets us share methods with the event class.
54
56
  def attr_type=(value)
55
57
  @event_type = value
56
58
  end
59
+
60
+ #attr_type retrieves the attribute type from the Event_record#event_type field.
61
+ #this minor hack lets us share methods with the event class.
57
62
  def attr_type
58
63
  @event_type
59
64
  end
65
+
66
+ #is_attribute? tests that this Individual_attribute_record is of this attribute type.
67
+ #The attribute type is stored in the the Event_record#event_type field.
68
+ #this minor hack lets us share methods with the event class.
69
+ #This make sense, as the GEDCOM INDIVIDUAL_ATTRIBUTE_STRUCTURE has GEDCOM <<EVENT_DETAIL>> tags at level +1.
70
+ def is_attribute?(attribute)
71
+ is_event?(attribute)
72
+ end
73
+
74
+ #value= stores the value in the Event_record#event_status.
75
+ #this minor hack lets us share methods with the event class.
60
76
  def value=(value)
61
- @event_status = value
77
+ @event_status = value
62
78
  end
79
+
80
+ #value retrieves the value from the Event_record#event_status.
81
+ #this minor hack lets us share methods with the event class.
63
82
  def value
64
83
  @event_status
65
84
  end
66
-
85
+
86
+ private
87
+
88
+ #actually attribute_tag, but we share code with the Event_record class,
89
+ #as the GEDCOM INDIVIDUAL_ATTRIBUTE_STRUCTURE has GEDCOM <<EVENT_DETAIL>> tags at level +1.
67
90
  def event_tag(tag)
68
91
  case tag
69
92
  when "SEX" then tag
@@ -98,31 +98,454 @@ class Individual_record < GEDCOMBase
98
98
  @individual_ref
99
99
  end
100
100
 
101
+ #Finds the parent's family record(s) and returns the Family_record object in an array.
102
+ #This allows for multiple parentage. There is usually only be one FAMC record, but their
103
+ #might be another recording an adoption or an alternate family, if parentage is not clear.
104
+ #Parents_family returns nil if there are no FAMC records (or the FAMC XREFs
105
+ #don't resolve to a FAM record in the transmission).
106
+ #
107
+ #If a block is passed, then each Family_record is yielded to the block.
101
108
  def parents_family
102
- parents_family = []
103
- @families_individuals.each { |m| parents_family << m.parents_family_ref if m.relationship_type == "FAMC"}
104
- parent_family
109
+ if @families_individuals
110
+ parent_families = []
111
+ @families_individuals.each do |p|
112
+ if p.relationship_type[0] == "FAMC"
113
+ if (parent_family = find(:family, p.parents_family_ref.first.xref_value)) != nil
114
+ parent_families << parent_family
115
+ yield parent_family if block_given?
116
+ end
117
+ end
118
+ end
119
+ return parent_families if parent_families.length > 0 #might be a 0 length array.
120
+ end
121
+ return nil
122
+ end
123
+
124
+ #child? is a consistency check, testing that this INDI record has a FAMC record to the given FAM record.
125
+ def child?(fam)
126
+ if (pf = parents_family) != nil
127
+ pf.each do |famc|
128
+ return true if famc == fam
129
+ end
130
+ end
131
+ return false
105
132
  end
106
133
 
134
+ #Finds the family record for each spouse (or fellow parent) and returns the Family_record objects in an array.
135
+ #This allows for being a parent of multiple families. Spouses will return nil if there are no
136
+ #FAMS records (or the FAMS XREFs don't resolve to a FAM record in the transmission).
137
+ #
138
+ #If a block is passed, then each Family_record is yielded to the block.
107
139
  def spouses
108
- spouses = []
109
- @families_individuals.each { |m| spouses << m.own_family if m.relationship_type == "FAMS"}
110
- spouses
140
+ if @families_individuals
141
+ spouses = []
142
+ @families_individuals.each do |s|
143
+ if s.relationship_type[0] == "FAMS"
144
+ #Make sure we can find the spouse's Family_record.
145
+ if (spouse_family = find(:family, s.family_ref.first.xref_value)) != nil
146
+ spouses << spouse_family
147
+ yield spouse_family if block_given?
148
+ end
149
+ end
150
+ end
151
+ return spouses if spouses.length > 0 #might be a 0 length array.
152
+ end
153
+ return nil
111
154
  end
112
155
 
113
- def birth
156
+ #spouse? is a consistency check, testing that this INDI record has a FAMS record to the given FAM record.
157
+ def spouse?(fam)
158
+ if (pf = spouses) != nil
159
+ pf.each do |fams|
160
+ return true if fams == fam
161
+ end
162
+ end
163
+ return false
164
+ end
165
+
166
+ #Event looks in the Individual_record for events, as specified by the type argument,
167
+ #returning an array of the events found. Returns nil if there were
168
+ #no events of this type in this Individual_record.
169
+ #
170
+ #If a block is given, then yields each event to the block.
171
+ def event(type)
114
172
  if @event_record != nil
115
- @event_record.each { |e| if e.is_event('BIRT') then return e end }
173
+ events = []
174
+ @event_record.each do |e|
175
+ if e.is_event?(type)
176
+ yield e if block_given?
177
+ events << e
178
+ end
179
+ end
180
+ return events if events.length > 0
181
+ end
182
+ return nil
183
+ end
184
+
185
+ #Short hand for event('BIRT')
186
+ #passes on any block to the event method.
187
+ #(The block is the &p argument, so you don't pass any arguments to this method).
188
+ def birth(&p)
189
+ if block_given? then event('BIRT',&p) else event('BIRT') end
190
+ end
191
+
192
+ #Short hand for event('CHR')
193
+ #passes on any block to the event method.
194
+ #(The block is the &p argument, so you don't pass any arguments to this method).
195
+ def christening(&p)
196
+ if block_given? then event('CHR',&p) else event('CHR') end
197
+ end
198
+
199
+ #Short hand for event('ADOP')
200
+ #passes on any block to the event method.
201
+ #(The block is the &p argument, so you don't pass any arguments to this method).
202
+ def adoption(&p)
203
+ if block_given? then event('ADOP',&p) else event('ADOP') end
204
+ end
205
+
206
+ #Short hand for event('DEAT')
207
+ #passes on any block to the event method.
208
+ #(The block is the &p argument, so you don't pass any arguments to this method).
209
+ def death(&p)
210
+ if block_given? then event('DEAT',&p) else event('DEAT') end
211
+ end
212
+
213
+ #Short hand for event('BURI')
214
+ #passes on any block to the event method.
215
+ #(The block is the &p argument, so you don't pass any arguments to this method).
216
+ def burial(&p)
217
+ if block_given? then event('BURI',&p) else event('BURI') end
218
+ end
219
+
220
+ #Short hand for event('CREM')
221
+ #passes on any block to the event method.
222
+ #(The block is the &p argument, so you don't pass any arguments to this method).
223
+ def cremation(&p)
224
+ if block_given? then event('CREM',&p) else event('CREM') end
225
+ end
226
+
227
+ #Short hand for event('WILL')
228
+ #passes on any block to the event method.
229
+ #(The block is the &p argument, so you don't pass any arguments to this method).
230
+ def will(&p)
231
+ if block_given? then event('WILL',&p) else event('WILL') end
232
+ end
233
+
234
+ #Short hand for event('PROB')
235
+ #passes on any block to the event method.
236
+ #(The block is the &p argument, so you don't pass any arguments to this method).
237
+ def probate(&p)
238
+ if block_given? then event('PROB',&p) else event('PROB') end
239
+ end
240
+
241
+ #Short hand for event('CENS')
242
+ #passes on any block to the event method.
243
+ #(The block is the &p argument, so you don't pass any arguments to this method).
244
+ def census(&p)
245
+ if block_given? then event('CENS',&p) else event('CENS') end
246
+ end
247
+
248
+ #Short hand for event('GRAD')
249
+ #passes on any block to the event method.
250
+ #(The block is the &p argument, so you don't pass any arguments to this method).
251
+ def graduation(&p)
252
+ if block_given? then event('GRAD',&p) else event('GRAD') end
253
+ end
254
+
255
+ #Short hand for event('RETI')
256
+ #passes on any block to the event method.
257
+ #(The block is the &p argument, so you don't pass any arguments to this method).
258
+ def retirement(&p)
259
+ if block_given? then event('RETI',&p) else event('RETI') end
260
+ end
261
+
262
+ #Short hand for event('BAPM')
263
+ #passes on any block to the event method.
264
+ #(The block is the &p argument, so you don't pass any arguments to this method).
265
+ def baptism(&p)
266
+ if block_given? then event('BAPM',&p) else event('BAPM') end
267
+ end
268
+
269
+ #Short hand for event('BARM')
270
+ #passes on any block to the event method.
271
+ #(The block is the &p argument, so you don't pass any arguments to this method).
272
+ def bar_mitzvah(&p)
273
+ if block_given? then event('BARM',&p) else event('BARM') end
274
+ end
275
+
276
+ #Short hand for event('BASM')
277
+ #passes on any block to the event method.
278
+ #(The block is the &p argument, so you don't pass any arguments to this method).
279
+ def bas_mitzvah(&p)
280
+ if block_given? then event('BASM',&p) else event('BASM') end
281
+ end
282
+
283
+ #Short hand for event('BLES')
284
+ #passes on any block to the event method.
285
+ #(The block is the &p argument, so you don't pass any arguments to this method).
286
+ def blessing(&p)
287
+ if block_given? then event('BLES',&p) else event('BLES') end
288
+ end
289
+
290
+ #Short hand for event('ORDN')
291
+ #passes on any block to the event method.
292
+ #(The block is the &p argument, so you don't pass any arguments to this method).
293
+ def ordination(&p)
294
+ if block_given? then event('ORDN',&p) else event('ORDN') end
295
+ end
296
+
297
+ #Short hand for event('CHRA')
298
+ #passes on any block to the event method.
299
+ #(The block is the &p argument, so you don't pass any arguments to this method).
300
+ def adult_christening(&p)
301
+ if block_given? then event('CHRA',&p) else event('CHRA') end
302
+ end
303
+
304
+ #Short hand for event('CONF')
305
+ #passes on any block to the event method.
306
+ #(The block is the &p argument, so you don't pass any arguments to this method).
307
+ def confirmation(&p)
308
+ if block_given? then event('CONF',&p) else event('CONF') end
309
+ end
310
+
311
+ #Short hand for event('FCOM')
312
+ #passes on any block to the event method.
313
+ #(The block is the &p argument, so you don't pass any arguments to this method).
314
+ def first_communion(&p)
315
+ if block_given? then event('FCOM',&p) else event('FCOM') end
316
+ end
317
+
318
+ #Short hand for event('NATU')
319
+ #passes on any block to the event method.
320
+ #(The block is the &p argument, so you don't pass any arguments to this method).
321
+ def naturalization(&p)
322
+ if block_given? then event('NATU',&p) else event('NATU') end
323
+ end
324
+
325
+ #Short hand for event('EMIG')
326
+ #passes on any block to the event method.
327
+ #(The block is the &p argument, so you don't pass any arguments to this method).
328
+ def emigration(&p)
329
+ if block_given? then event('EMIG',&p) else event('EMIG') end
330
+ end
331
+
332
+ #Short hand for event('IMMI')
333
+ #passes on any block to the event method.
334
+ #(The block is the &p argument, so you don't pass any arguments to this method).
335
+ def immigration(&p)
336
+ if block_given? then event('IMMI',&p) else event('IMMI') end
337
+ end
338
+
339
+ #Short hand for the event('BAPL') LDS Ordinance
340
+ #passes on any block to the event method.
341
+ #(The block is the &p argument, so you don't pass any arguments to this method).
342
+ def lds_baptism(&p)
343
+ if block_given? then event('BAPL',&p) else event('BAPL') end
344
+ end
345
+
346
+ #Short hand for the event('CONL') LDS Ordinance
347
+ #passes on any block to the event method.
348
+ #(The block is the &p argument, so you don't pass any arguments to this method).
349
+ def lds_confirmation(&p)
350
+ if block_given? then event('CONL',&p) else event('CONL') end
351
+ end
352
+
353
+ #Short hand for the event('ENDL') LDS Ordinance
354
+ #passes on any block to the event method.
355
+ #(The block is the &p argument, so you don't pass any arguments to this method).
356
+ def lds_endowment(&p)
357
+ if block_given? then event('ENDL',&p) else event('ENDL') end
358
+ end
359
+
360
+ #Short hand for the event('SLGC') LDS Ordinance
361
+ #passes on any block to the event method.
362
+ #(The block is the &p argument, so you don't pass any arguments to this method).
363
+ def lds_child_sealing(&p)
364
+ if block_given? then event('SLGC',&p) else event('SLGC') end
365
+ end
366
+
367
+ #Short hand for the event('SLGS') LDS Sealing
368
+ #passes on any block to the event method.
369
+ #(The block is the &p argument, so you don't pass any arguments to this method).
370
+ def lds_spouse_sealing(&p)
371
+ if block_given? then event('SLGS',&p) else event('SLGS') end
372
+ end
373
+
374
+ #Attribute looks in the Individual_record for attributes, as specified by the attribute argument,
375
+ #returning an array of the attrbutes found. This may be a 0 length array, if there were
376
+ #no attrbutes of this type in this Individual_record.
377
+ #
378
+ #If a block is given, then yields each event to the block.
379
+ def attribute(attribute)
380
+ if @individual_attribute_record != nil
381
+ attributes = [] #collect the individual_attribute_record's of type attribute in this array.
382
+ @individual_attribute_record.each do |a|
383
+ #Look for the attribute in question.
384
+ if a.is_attribute?(attribute)
385
+ yield a if block_given?
386
+ attributes << a #add this record to the attributes array.
387
+ end
388
+ end
389
+ return attributes if attributes.length > 0 #if we found any, return the array.
390
+ end
391
+ return nil #if we found none, then return nil.
392
+ end
393
+
394
+ #Short hand for attribute('SEX')
395
+ #passes on any block to the event method.
396
+ #(The block is the &p argument, so you don't pass any arguments to this method).
397
+ def sex(&p)
398
+ if block_given? then attribute('SEX',&p) else attribute('SEX') end
399
+ end
400
+
401
+ #Short hand for attribute('CAST')
402
+ #passes on any block to the event method.
403
+ #(The block is the &p argument, so you don't pass any arguments to this method).
404
+ def caste_name(&p)
405
+ if block_given? then attribute('CAST',&p) else attribute('CAST') end
406
+ end
407
+
408
+ #Short hand for attribute('DSCR')
409
+ #passes on any block to the event method.
410
+ #(The block is the &p argument, so you don't pass any arguments to this method).
411
+ def physical_description(&p)
412
+ if block_given? then attribute('DSCR',&p) else attribute('DSCR') end
413
+ end
414
+
415
+ #Short hand for attribute('EDUC')
416
+ #passes on any block to the event method.
417
+ #(The block is the &p argument, so you don't pass any arguments to this method).
418
+ def education(&p)
419
+ if block_given? then attribute('EDUC',&p) else attribute('EDUC') end
420
+ end
421
+
422
+ #Short hand for attribute('IDNO')
423
+ #passes on any block to the event method.
424
+ #(The block is the &p argument, so you don't pass any arguments to this method).
425
+ def national_id_number(&p)
426
+ if block_given? then attribute('IDNO',&p) else attribute('IDNO') end
427
+ end
428
+
429
+ #Short hand for attribute('NATI')
430
+ #passes on any block to the event method.
431
+ #(The block is the &p argument, so you don't pass any arguments to this method).
432
+ def national_origin(&p)
433
+ if block_given? then attribute('NATI',&p) else attribute('NATI') end
434
+ end
435
+
436
+ #Short hand for attribute('NCHI')
437
+ #passes on any block to the event method.
438
+ #(The block is the &p argument, so you don't pass any arguments to this method).
439
+ def number_children(&p)
440
+ if block_given? then attribute('NCHI',&p) else attribute('NCHI') end
441
+ end
442
+
443
+ #Short hand for attribute('NMR')
444
+ #passes on any block to the event method.
445
+ #(The block is the &p argument, so you don't pass any arguments to this method).
446
+ def marriage_count(&p)
447
+ if block_given? then attribute('NMR',&p) else attribute('NMR') end
448
+ end
449
+
450
+ #Short hand for attribute('OCCU')
451
+ #passes on any block to the event method.
452
+ #(The block is the &p argument, so you don't pass any arguments to this method).
453
+ def occupation(&p)
454
+ if block_given? then attribute('OCCU',&p) else attribute('OCCU') end
455
+ end
456
+
457
+ #Short hand for attribute('PROP')
458
+ #passes on any block to the event method.
459
+ #(The block is the &p argument, so you don't pass any arguments to this method).
460
+ def possessions(&p)
461
+ if block_given? then attribute('PROP',&p) else attribute('PROP') end
462
+ end
463
+
464
+ #Short hand for attribute('RELI')
465
+ #passes on any block to the event method.
466
+ #(The block is the &p argument, so you don't pass any arguments to this method).
467
+ def religion(&p)
468
+ if block_given? then attribute('RELI',&p) else attribute('RELI') end
469
+ end
470
+
471
+ #Short hand for attribute('RESI')
472
+ #passes on any block to the event method.
473
+ #(The block is the &p argument, so you don't pass any arguments to this method).
474
+ def residence(&p)
475
+ if block_given? then attribute('RESI',&p) else attribute('RESI') end
476
+ end
477
+
478
+ #Short hand for attribute('SSN')
479
+ #passes on any block to the event method.
480
+ #(The block is the &p argument, so you don't pass any arguments to this method).
481
+ def social_security_number(&p)
482
+ if block_given? then attribute('SSN',&p) else attribute('SSN') end
483
+ end
484
+
485
+ #Short hand for attribute('TITL')
486
+ #passes on any block to the event method
487
+ #(The block is the &p argument, so you don't pass any arguments to this method).
488
+ def title(&p)
489
+ if block_given? then attribute('TITL',&p) else attribute('TITL') end
490
+ end
491
+
492
+ #Test to see if we have a NAME record stored for this individual.
493
+ def has_name?
494
+ @name_record != nil && @name_record.length > 0
495
+ end
496
+
497
+ #Names looks in the Individual_record for Name_records, returning an array of the Name_records found.
498
+ #This may be a 0 length array, if there were no NAME tags in this GEDCOM record for this Individual_record.
499
+ #
500
+ #If a block is given, then yields each event to the block.
501
+ def names
502
+ if has_name?
503
+ if block_given?
504
+ @name_record.each { |n| yield n }
505
+ end
506
+ return @name_record
116
507
  else
117
- nil
508
+ return []
118
509
  end
119
510
  end
120
511
 
121
- def death
122
- if @event_record != nil
123
- @event_record.each { |e| if e.is_event('DEAT') then return e end }
512
+ #Primary_name returns the first name (as a string) defined in the @name_record array (and probably the only name defined).
513
+ #The GEDCOM standard states that if multiple TAGS of the same type are present, then the first is the most
514
+ #preferred, with the last the least preferred. I'm not certain that programs generating GEDCOM follow that rule,
515
+ #but if there are multiple NAME records, and you want one to display, then picking the first is what the standard
516
+ #says to do.
517
+ #
518
+ #Returns "" if no name is recorded in this Individual_record and if the individual requested privacy for this record.
519
+ def primary_name
520
+ if has_name?
521
+ if self.private? || @name_record[0].private?
522
+ ""
523
+ else
524
+ @name_record[0].name
525
+ end
526
+ else
527
+ ""
528
+ end
529
+ end
530
+
531
+ def self_check
532
+ if @families_individuals
533
+ @families_individuals.each do |p|
534
+ if p.relationship_type[0] == "FAMC"
535
+ if find(:family, p.parents_family_ref.first.xref_value) == nil
536
+ puts "INDI #{@individual_ref.first.xref_value} FAMC #{p.parents_family_ref.first.xref_value} record has no FAM record"
537
+ end
538
+ elsif p.relationship_type[0] == "FAMS"
539
+ if find(:family, p.family_ref.first.xref_value) == nil
540
+ puts "INDI #{@individual_ref.first.xref_value} FAMS #{p.family_ref.first.xref_value} record has no FAM record"
541
+ end
542
+ else
543
+ puts "Unrecognised relationship #{p.relationship_type[0]}"
544
+ end
545
+ end
124
546
  else
125
- nil
547
+ puts "INDI #{@individual_ref.first.xref_value} has no FAMC or FAMS record"
126
548
  end
127
549
  end
550
+
128
551
  end