gedcom 0.9.0 → 0.9.1

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.
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
File without changes
File without changes
@@ -27,6 +27,44 @@ require 'individual_attribute_record.rb'
27
27
  # (6.0 and later) will likely apply a very different strategy to resolve this problem, possibly using a
28
28
  # sophisticated parser and a name-knowledge database.
29
29
  #
30
+ #==NAME_PERSONAL:= {Size=1:120}
31
+ # <TEXT> | /<TEXT>/ | <TEXT> /<TEXT>/ | /<TEXT>/ <TEXT> | <TEXT> /<TEXT>/ <TEXT>
32
+ #
33
+ # The surname of an individual, if known, is enclosed between two slash (/) characters. The order of the
34
+ # name parts should be the order that the person would, by custom of their culture, have used when
35
+ # giving it to a recorder. Early versions of Personal Ancestral File and other products did not use the ®
36
+ # trailing slash when the surname was the last element of the name. If part of name is illegible, that part
37
+ # is indicated by an ellipsis (...). Capitalize the name of a person or place in the conventional
38
+ # manner—capitalize the first letter of each part and lowercase the other letters, unless conventional
39
+ # usage is otherwise. For example: McMurray.
40
+ # Examples:
41
+ # 1 NAME William Lee (given name only or surname not known)
42
+ # 1 NAME /Parry/ (surname only)
43
+ # 1 NAME William Lee /Parry/
44
+ # 1 NAME William Lee /Mac Parry/ (both parts (Mac and Parry) are surname parts
45
+ # 1 NAME William /Lee/ Parry (surname imbedded in the name string)
46
+ # 1 NAME William Lee /Pa.../
47
+ # 1 NAME /HU/ Pan (Surname before firstname)
48
+ #
49
+ #==NAME_PIECE:= {Size=1:90}
50
+ # The piece of the name pertaining to the name part of interest. The surname part, the given name part,
51
+ # the name prefix part, or the name suffix part.
52
+ #
53
+ #==NAME_PIECE_GIVEN:= {Size=1:120}
54
+ # <NAME_PIECE> | <NAME_PIECE_GIVEN>, <NAME_PIECE>
55
+ #
56
+ # Given name or earned name. Different given names are separated by a comma.
57
+ #
58
+ #==NAME_PIECE_NICKNAME:= {Size=1:30}
59
+ # <NAME_PIECE> | <NAME_PIECE_NICKNAME>, <NAME_PIECE>
60
+ # A descriptive or familiar name used in connection with one's proper name.
61
+ #
62
+ #==NAME_PIECE_PREFIX:= {Size=1:30}
63
+ # <NAME_PIECE> | <NAME_PIECE_PREFIX>, <NAME_PIECE>
64
+ #
65
+ # Non indexing name piece that appears preceding the given name and surname parts. Different name
66
+ # prefix parts are separated by a comma.
67
+ #
30
68
  #The attributes are all arrays for the level +1 tags/records.
31
69
  #* Those ending in _ref are GEDCOM XREF index keys
32
70
  #* Those ending in _record are array of classes of that type.
@@ -54,5 +92,37 @@ class Name_record < Individual_attribute_record
54
92
  end
55
93
  end
56
94
 
95
+ #return the name as a string. It might be returned be the Individual_attribute_record#value method.
96
+ # or it might need to be contructed from the Name_record attributes. 99.9999% of all GEDCOM I have
97
+ # seen does not use the Name_record attributes, and if the do, they are required to fill in the name on the
98
+ # NAME line (NAME_PERSONAL value), so the value should be set. This helps, as the ordering of the surname and
99
+ # first names is not standard across all cultures.
100
+ def name
101
+ if (name = value) == nil
102
+ name = "" #could be what we return if none of the Name_record attributes are set
103
+ if @prefix
104
+ name += @prefix.first
105
+ name += ' ' if @given || @nickname || @surname_prefix || @surname || @suffix
106
+ end
107
+ if @given
108
+ name += @given.first
109
+ name += ' ' if @nickname || @surname_prefix || @surname || @suffix
110
+ end
111
+ if @nickname
112
+ name += '(' + @nickname.first + ')'
113
+ name += ' ' if @surname_prefix || @surname || @suffix
114
+ end
115
+ if @surname_prefix
116
+ name += @surname_prefix.first
117
+ name += ' ' if @surname || @suffix
118
+ end
119
+ if @surname
120
+ name += ( '/' + @surname.first + '/' )
121
+ name += ' ' if @suffix
122
+ end
123
+ name += @suffix.first if @suffix
124
+ end
125
+ return name.first
126
+ end
57
127
  end
58
128
 
File without changes
File without changes
@@ -43,4 +43,10 @@ class Place_record < GEDCOMBase
43
43
  end
44
44
  super(level)
45
45
  end
46
+
47
+ #When wanting just one place, the GEDCOM standard says to use the first PLAC record.
48
+ #If you want all the PLAC records, then use @place_value, which is an array PLAC's.
49
+ def place
50
+ @place_value ? @place_value.first : ''
51
+ end
46
52
  end
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -88,6 +88,15 @@ class Transmission < TransmissionBase
88
88
  end
89
89
  end
90
90
  end
91
+
92
+ def self_check
93
+ @family_record.each do |f|
94
+ f.self_check
95
+ end
96
+ @individual_record.each do |i|
97
+ i.self_check
98
+ end
99
+ end
91
100
  =begin
92
101
  def summary
93
102
  @@tabs = true
@@ -6,6 +6,14 @@ require 'gedcom_base.rb'
6
6
  #the fields based on the parsed GEDCOM file.
7
7
  class TransmissionBase < GEDCOMBase
8
8
 
9
+ #Class_stack is for the parsing process to hold the classes we create as we walk down the levels of a gedcom record.
10
+ #The class we are currently working with is on the top of the stack.
11
+ #The put ourselves on the top of the stack. The number represents the number of class to pop to go back one level of gedcom.
12
+ attr_accessor :class_stack
13
+
14
+ #A hash to hold the indexes used in this transmission, each of which is also a hash (though that may change)
15
+ attr_accessor :indexes
16
+
9
17
  ClassTracker << :TransmissionBase
10
18
 
11
19
  #new creates initializes the arrays for each of the GEDCOM level 0 record types.
@@ -27,8 +35,19 @@ class TransmissionBase < GEDCOMBase
27
35
  #The class we are currently working with is on the top of the stack.
28
36
  #The put ourselves on the top of the stack. The number represents the number of class to pop to go back one level of gedcom.
29
37
  @class_stack = [[self, 0]]
38
+
30
39
  #Create a hash to hold the indexes used in this transmission
31
- @indexes = {} #find is defined in GEDCOMBase, as it gets used by a private method of that class.
40
+ #Set up default indexes for the known level 0 types, so we can reference them even if they have no members.
41
+ @indexes = {
42
+ :individual => {},
43
+ :family => {},
44
+ :note => {},
45
+ :source => {},
46
+ :repository => {},
47
+ :multimedia => {},
48
+ :submitter => {},
49
+ :submission => {}
50
+ }
32
51
  end
33
52
 
34
53
  #summary() prints out the number of each level 0 record type the we have just parsed.
@@ -85,26 +104,30 @@ class TransmissionBase < GEDCOMBase
85
104
  end
86
105
 
87
106
  #add_to_class_field() is part of the parsing process, and checks to see if the field exists in the current states, target object.
88
- #If the field exists, then the data is added to the field array. Each field is an array, so we can have multiple instances of a TAG in a GEDCOM record.
89
- #If the field doesn't exist, the field is added to the target object, along with attr_accessors. The data is then added as above.
107
+ #If the record exists, then the data is added to the record array. Each record is an array, so we can have multiple instances of a TAG in a GEDCOM record.
108
+ #If the record doesn't exist, the record is added to the target object, along with attr_accessors. The data is then added as above.
90
109
  #* lineno is the current GEDCOM files line number, so we can report errors.
91
- #* field is a symbol naming the attribute we want to store the data in in the class.
110
+ #* record is a symbol naming the attribute we want to store the data in in the class.
92
111
  #* data is a word array, holding the GEDCOM lines data value
93
- def add_to_class_field(lineno, field, data)
94
- #puts "#{lineno}: Add class instance '#{data.class}' to field #{field} of #{@class_stack.last[0]}"
95
- if @class_stack.last[0].class.method_defined?(field) == false
96
- p "#{lineno}: create a field called #{field} in class #{@class_stack.last[0].class.to_s}"
97
- @class_stack.last[0].class.class_eval("attr_accessor :#{field}")
98
- #p "#{lineno}: Add the class #{data.class.to_s} as an array, to the field #{field} in class #{@class_stack.last[0].class.to_s}"
99
- @class_stack.last[0].send( field.to_s + "=", data ? [ data ] : []) #Much faster than eval("@class_stack.last[0].#{field} = [#{data}]")
112
+ def add_to_class_field(lineno, record, data)
113
+ #puts "#{lineno}: Add class instance '#{data.class}' to record #{record} of #{@class_stack.last[0]}"
114
+ if @class_stack.last[0].class.method_defined?(record) == false
115
+ #record is missing from the class, so add it using attr_accessor, thus getting the get and set methods.
116
+ #Unlikely to ever see this case, as we precreated all fields for all class needed for GEDCOM 5.5
117
+ p "#{lineno}: create a record called #{record} in class #{@class_stack.last[0].class.to_s}"
118
+ @class_stack.last[0].class.class_eval("attr_accessor :#{record}")
119
+ #p "#{lineno}: Add the class #{data.class.to_s} as an array, to the record #{record} in class #{@class_stack.last[0].class.to_s}"
120
+ @class_stack.last[0].send( record.to_s + "=", data ? [ data ] : []) #Much faster than eval("@class_stack.last[0].#{record} = [#{data}]")
100
121
  else
101
- if a = @class_stack.last[0].send( field )
102
- #Much faster than eval("@class_stack.last[0].#{field} << #{data}")
103
- #p "#{lineno}: Add the class #{data.class.to_s} to the field #{field}[] in class #{@class_stack.last[0].class.to_s}"
122
+ #record exists, get a reference to it, so we can just add the data to the record's data array.
123
+ if (a = @class_stack.last[0].send( record ) ) != nil
124
+ #This way is much faster than eval("@class_stack.last[0].#{record} << #{data}")
125
+ #p "#{lineno}: Add the class #{data.class.to_s} to the record #{record}[] in class #{@class_stack.last[0].class.to_s}"
104
126
  a << data if data != nil
105
127
  else
106
- #p "#{lineno}: Add the class #{data.class.to_s} as an array, to the field #{field} in class #{@class_stack.last[0].class.to_s}"
107
- @class_stack.last[0].send( field.to_s + "=", data ? [ data ] : [] )
128
+ #Got a reference to the attribute in the class, but no value stored as yet.
129
+ #p "#{lineno}: Add the class #{data.class.to_s} as an array, to the record #{record} in class #{@class_stack.last[0].class.to_s}"
130
+ @class_stack.last[0].send( record.to_s + "=", data ? [ data ] : [] )
108
131
  end
109
132
  end
110
133
  end
@@ -118,54 +141,70 @@ class TransmissionBase < GEDCOMBase
118
141
  i.times { @class_stack.pop }
119
142
  end
120
143
 
121
- #update_field() is part of the parsing process, and discards the data_type and calls add_to_class_field.
144
+ #update_field() is part of the parsing process, calls add_to_class_field.
122
145
  #I'm sure there is a reason I did this. I just can't think what it was.
123
146
  #* lineno is the current GEDCOM files line number, so we can report errors.
124
147
  #* field is a symbol naming the attribute we want to store the data in in the class.
125
148
  #* data is a word array, holding the GEDCOM lines data value
149
+ #* data_type gives hints to help validate the data (which we don't yet do).
126
150
  def update_field(lineno, field, data_type, data)
127
151
  #p "#{lineno}: Add data '#{data}' to field #{field} of #{@class_stack.last[0]}"
128
- add_to_class_field(lineno, field, data)
152
+ add_to_class_field(lineno, field, data == nil ? nil : GedString.new(data))
153
+ end
154
+
155
+ #append_sp_field is part of the parsing process, and inserts a ' ' character in front of the data, then calls append_to_field.
156
+ #* lineno is the current GEDCOM files line number, so we can report errors.
157
+ #* field is a symbol naming the attribute we want to store the data in in the class.
158
+ #* data is a word array, holding the GEDCOM lines data value
159
+ #* data_type gives hints to help validate the data (which we don't yet do).
160
+ def append_sp_field(lineno, field, data_type, data)
161
+ #p "#{lineno}: Append data ' #{data}' to field #{field} of #{@class_stack.last[0]}"
162
+ the_data = [" "] #want to add a space to the existing data, before adding it to the string.
163
+ the_data += data if data != nil #add the new data only if it is not null.
164
+ append_to_field(lineno, field, data_type, the_data)
129
165
  end
130
166
 
131
- #append_nl_field() is part of the parsing process, and inserts a '\n' character in front of the data, then calls append_field().
167
+ #append_nl_field is part of the parsing process, and inserts a '\n' character in front of the data, then calls append_to_field.
132
168
  #* lineno is the current GEDCOM files line number, so we can report errors.
133
169
  #* field is a symbol naming the attribute we want to store the data in in the class.
134
170
  #* data is a word array, holding the GEDCOM lines data value
171
+ #* data_type gives hints to help validate the data (which we don't yet do).
135
172
  def append_nl_field(lineno, field, data_type, data)
136
- #p "#{lineno}: Append data 'nl + #{data}' to field #{field} of #{@class_stack.last[0]}"
173
+ #p "#{lineno}: Append data '\n#{data}' to field #{field} of #{@class_stack.last[0]}"
137
174
  the_data = ["\n"] #want to add a new line to the existing data
138
175
  the_data += data if data != nil #add the new data only if it is not null.
139
- append_field(lineno, field,data_type, the_data)
176
+ append_to_field(lineno, field, data_type, the_data)
140
177
  end
141
178
 
142
- #append_field() is part of the parsing process, and adds the data to the end of the field's array.
179
+ #append_to_field is part of the parsing process, and adds the data to the end of the field's array.
180
+ #Shared code between append_sp_field and append_nl_field.
143
181
  #* lineno is the current GEDCOM files line number, so we can report errors.
144
182
  #* field is a symbol naming the attribute we want to store the data in in the class.
145
183
  #* data is a word array, holding the GEDCOM lines data value
146
- def append_field(lineno, field, data_type, data)
184
+ #* data_type gives hints to help validate the data (which we don't yet do).
185
+ def append_to_field(lineno, field, data_type, data)
147
186
  #p "#{lineno}: Append data '#{data}' to field #{field} of #{@class_stack.last[0]}"
148
187
  begin
149
- if data != nil#Only bother if we have some data
150
- if a = @class_stack.last[0].send( field ) #The field is not nil
188
+ if data != nil #Only bother if we have some data to append
189
+ if ( a = @class_stack.last[0].send( field ) ) != nil #The field is not nil, then we need to add to the last value in the array
151
190
  if a != [] #The field is not an empty array
152
- if a[-1] != nil #The last element is not null
191
+ if a[-1] != nil #The last element is not null, so we append to it.
153
192
  #p "Add the class #{data.class.to_s} to the field #{field}[] in class #{@class_stack.last[0].class.to_s}"
154
- a[-1] += data
155
- else #The last element is null
193
+ a[-1] << GedString.new(data)
194
+ else #The last element is null, so we replace is, rather than append to it.
156
195
  #p "Add the class #{data.class.to_s} as an array, to the field #{field} in class #{@class_stack.last[0].class.to_s}"
157
- a[-1] = data
196
+ a[-1] = GedString.new(data)
158
197
  end
159
- else #Was an empty array, so add the element.
160
- a[0] = data
198
+ else #Was an empty array, the data will be the first member in the array.
199
+ a[0] = GedString.new(data)
161
200
  end
162
- else #The field was null
201
+ else #The field was null. We need to set the first value to our data value, in an array.
163
202
  #p "Add the class #{data.class.to_s} as an array, to the field #{field} in class #{@class_stack.last[0].class.to_s}"
164
- @class_stack.last[0].send( field.to_s + '=', [data])
203
+ @class_stack.last[0].send( field.to_s + '=', [ GedString.new(data) ] )
165
204
  end
166
205
  end
167
206
  rescue => exception
168
- p "#{exception} : Append data '#{data}' to field '#{field}' of class '#{@class_stack.last[0]}'"
207
+ p "#{exception} : Append data '#{data}' to field '#{field}' of class '#{@class_stack.last[0].class}'"
169
208
  raise exception
170
209
  end
171
210
  end
@@ -194,7 +233,9 @@ class TransmissionBase < GEDCOMBase
194
233
  #add_to_index is part of the parsing process, and adds references into the current target object to the index (i.e fills in the XREFs with index references]
195
234
  def add_to_index(lineno, field_name, index_name, key)
196
235
  #p "#{lineno}: Add key #{key} to index #{index_name} to field #{field_name} of #{@class_stack.last[0]}"
197
- add_to_class_field(lineno, field_name, [index_name, *key] )
236
+ #There are many cases where there can be multiple records of the same GEDCOM type, in the parent record, so we store these in an array.
237
+ #e.g. CHIL xrefs can occur multiple times in FAM record.
238
+ add_to_class_field(lineno, field_name, Xref.new(index_name, *key) )
198
239
  end
199
240
 
200
241
  #action_handler process the actions in the GedcomParser::TAGS hash, creating classes and populating attributes.
@@ -222,7 +263,7 @@ class TransmissionBase < GEDCOMBase
222
263
  when :class
223
264
  #create a new class, making an instance of it, and making the instance the default one.
224
265
  new_class = create_class(lineno, do_this[DATA])
225
- #Add this instance to an Array field of the current class, of the same name as the new class.
266
+ #Add this instance to an Array of records as an attribute named new_class of the current class.
226
267
  add_to_class_field(lineno, do_this[DATA], new_class)
227
268
  #Make this class the current one
228
269
  @class_stack << [new_class, nclasses]
@@ -236,15 +277,18 @@ class TransmissionBase < GEDCOMBase
236
277
  end
237
278
  when :append_nl
238
279
  #We want to add a line terminator, then append the new data field from tokens
280
+ #e.g. We do this with CONT lines being appended to a NOTE.
239
281
  append_nl_field(lineno, do_this[DATA], data_type, tokens.data)
240
282
  when :append
241
283
  #we want to append the data field in tokens, to the named field.
242
- append_field(lineno, do_this[DATA], data_type, tokens.data)
284
+ #e.g. We do this with CONC lines being added to a NOTE.
285
+ append_sp_field(lineno, do_this[DATA], data_type, tokens.data)
243
286
  when :xref
244
287
  #we want to record the reference (xref) from the token object.
245
288
  add_to_index(lineno, do_this[DATA][0], do_this[DATA][1], tokens.xref)
246
289
  when :key
247
290
  #will only occur after a class that is the thing we want the xref index to point to. ie xref => new_class
291
+ #All the level 0 indexes should exist already, as it helps to have them, even if they are empty.
248
292
  create_index(lineno, do_this[DATA], tokens.xref, new_class )
249
293
  when :pop
250
294
  @class_stack.pop #In this instance, we want to remove only the last item, even if there were several added.
@@ -0,0 +1,8 @@
1
+ #Utility class just to make referencing xrefs clearer.
2
+
3
+ class Xref
4
+ attr_accessor :index, :xref_value
5
+ def initialize(index, xref_value)
6
+ @index, @xref_value = index, xref_value
7
+ end
8
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ #Or 1.9 version at
3
+ #!/usr/local/bin/ruby
4
+ require '../lib/gedcom.rb'
5
+ require 'ruby_version.rb'
6
+
7
+
8
+
9
+ puts RubyVersion.to_s
10
+
11
+ #Parses the LDS GEDCOM test files and them dumps them back out as GEDCOM.
12
+ #This allows me to test for errors in parsing and output. The two files will
13
+ #not be an exact match, as the NOTE/CONT/CONC line breaks could be different
14
+ #and user defined tags will get converted to NOTES.
15
+
16
+ puts "parse TGC551LF.ged"
17
+ if RubyVersion.have_at_least_version?(1,9)
18
+ g = Gedcom.file("../test_data/TGC551LF.ged", "r:ASCII-8BIT") #OK with LF line endings.
19
+ else
20
+ g = Gedcom.file("../test_data/TGC551LF.ged", "r") #OK with LF line endings.
21
+ end
22
+ g.transmissions[0].summary
23
+ puts
24
+
25
+ g.transmissions[0].self_check
26
+
27
+ #puts g.transmissions[0].header_record[0].to_s
28
+ puts
29
+ #f = g.transmissions[0].find(:individual,"PERSON1")
30
+ #puts f.to_s
31
+
32
+ #puts "parse TGC55CLF.ged"
33
+ #g.file("../test_data/TGC55CLF.ged", "r:ASCII-8BIT") #Ok with CR LF line endings.
34
+ #g.transmissions[1].summary
35
+ #puts
36
+
37
+ #g.file("../test_data/TGC551.ged") #fails to find CR line breaks, as native system uses LF, so reports parse error.
38
+ #g.file("../test_data/TGC55C.ged") #fails to find CR line breaks, as native system uses LF, so reports parse error.
39
+
40
+ #print the parsed file to see if it matches the source file.
41
+ #Note CONT and CONC breaks may end up in different places
42
+ #Note Order of TAGS at the same level may be different
43
+ #Note User TAGS are output as Notes.
44
+ if RubyVersion.have_at_least_version?(1,9)
45
+ File.open( "../test_data/TGC551LF.out", "w:ASCII-8BIT") do |file|
46
+ file.print g.transmissions[0].to_gedcom
47
+ end
48
+ else
49
+ File.open( "../test_data/TGC551LF.out", "w") do |file|
50
+ file.print g.transmissions[0].to_gedcom
51
+ end
52
+ end
53
+
54
+ #File.open( "../test_data/TGC55CLF.out", "w:ASCII-8BIT") do |file|
55
+ # file.print g.transmissions[1].to_gedcom
56
+ #end
57
+ puts "\nComplete"
58
+ c = Chart.new
59
+ #puts c.output_pedigree_name( f, 10, nil, nil, Bit.new, '', '', nil, '', 0 )
60
+
61
+
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ class RubyVersion
4
+ #self.have_version tests that the versien of RUBY is the one we want.
5
+ def self.have_version?(major, minor, update = nil, build = nil)
6
+ v = RUBY_VERSION.split('.')
7
+ if major == v[0].to_i && minor == v[1].to_i
8
+ return false if update != nil && update != v[2].to_i
9
+ return false if build != nil && build != RUBY_PATCHLEVEL.to_i
10
+ return true
11
+ else
12
+ return false
13
+ end
14
+ end
15
+
16
+ #self.have_at_least_version tests that the versien of RUBY is newer than the one we want.
17
+ def self.have_at_least_version?(major, minor, update = nil, build = nil)
18
+ v = RUBY_VERSION.split('.')
19
+ if major == v[0].to_i #Could true
20
+ if minor == v[1].to_i #Could be true
21
+ if update != nil #Being asked to test update level
22
+ if update == v[2].to_i #Could be true
23
+ if build != nil #Being asked to test the build version
24
+ return build <= RUBY_PATCHLEVEL.to_i #have at least the required patch level.
25
+ end
26
+ return true #update was equal
27
+ end
28
+ return update < v[2].to_i #current version is newer
29
+ end
30
+ return true #major and minor was equal.
31
+ end
32
+ return minor < v[1].to_i #true if current version is newer
33
+ end
34
+ return major < v[0].to_i #true, if current version is newer
35
+ end
36
+
37
+ def self.to_s
38
+ "RUBY #{RUBY_VERSION} Build #{RUBY_PATCHLEVEL}"
39
+ end
40
+ end
41
+
42
+ #puts RubyVersion.to_s
43
+ #puts RubyVersion.have_version?(1,9)