ruby-fs-stack 0.1.7
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/.document +5 -0
- data/.gitignore +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +26 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/examples/familytree_example.rb +26 -0
- data/examples/login_example.rb +11 -0
- data/lib/ruby-fs-stack/assets/entrust-ca.crt +104 -0
- data/lib/ruby-fs-stack/enunciate/LICENSE +15 -0
- data/lib/ruby-fs-stack/enunciate/README +6 -0
- data/lib/ruby-fs-stack/enunciate/familytree.rb +12608 -0
- data/lib/ruby-fs-stack/enunciate/identity.rb +964 -0
- data/lib/ruby-fs-stack/familytree.rb +827 -0
- data/lib/ruby-fs-stack/fs_communicator.rb +109 -0
- data/lib/ruby-fs-stack/fs_utils.rb +27 -0
- data/lib/ruby-fs-stack/identity.rb +45 -0
- data/lib/ruby-fs-stack/warning_suppressor.rb +18 -0
- data/lib/ruby-fs-stack.rb +2 -0
- data/spec/communicator_spec.rb +214 -0
- data/spec/familytree_v2/familytree_communicator_spec.rb +309 -0
- data/spec/familytree_v2/json/match_KW3B-NNM.js +1 -0
- data/spec/familytree_v2/json/person/KJ86-3VD_all.js +1 -0
- data/spec/familytree_v2/json/person/KJ86-3VD_version.js +1 -0
- data/spec/familytree_v2/json/person/post_response.js +1 -0
- data/spec/familytree_v2/json/person/relationship_not_found.js +1 -0
- data/spec/familytree_v2/json/person/relationship_read.js +1 -0
- data/spec/familytree_v2/json/person/relationship_update.js +1 -0
- data/spec/familytree_v2/json/search.js +1 -0
- data/spec/familytree_v2/person_spec.rb +563 -0
- data/spec/familytree_v2/search_results_spec.rb +131 -0
- data/spec/fs_utils_spec.rb +33 -0
- data/spec/identity_v1/identity_spec.rb +50 -0
- data/spec/identity_v1/json/login.js +1 -0
- data/spec/ruby-fs-stack_spec.rb +6 -0
- data/spec/spec_helper.rb +27 -0
- metadata +119 -0
@@ -0,0 +1,827 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'ruby-fs-stack/fs_communicator'
|
3
|
+
require 'ruby-fs-stack/fs_utils'
|
4
|
+
|
5
|
+
# Including more than one enunciate library raises a warning of
|
6
|
+
# already initialized constant.
|
7
|
+
require 'ruby-fs-stack/warning_suppressor'
|
8
|
+
with_warnings_suppressed do
|
9
|
+
require 'ruby-fs-stack/enunciate/familytree'
|
10
|
+
end
|
11
|
+
|
12
|
+
|
13
|
+
module FamilytreeV2
|
14
|
+
|
15
|
+
# This method gets mixed into the FsCommunicator so that
|
16
|
+
# you can make calls on the familytree_v2 module
|
17
|
+
def familytree_v2
|
18
|
+
@familytree_v2_com ||= Communicator.new self # self at this point refers to the FsCommunicator instance
|
19
|
+
end
|
20
|
+
|
21
|
+
class Communicator
|
22
|
+
Base = '/familytree/v2/'
|
23
|
+
|
24
|
+
# ===params
|
25
|
+
# fs_communicator: FsCommunicator instance
|
26
|
+
def initialize(fs_communicator)
|
27
|
+
@fs_communicator = fs_communicator
|
28
|
+
end
|
29
|
+
|
30
|
+
# ===params
|
31
|
+
# <tt>id</tt> should be a string of the persons identifier. For the 'me' person, use :me or 'me'
|
32
|
+
# <tt>options</tt> accepts a hash of parameters as documented by the API.
|
33
|
+
# For full parameter documentation, see DevNet[https://devnet.familysearch.org/docs/api-manual-reference-system/familytree-v2/r_api_family_tree_person_read_v2.html]
|
34
|
+
#
|
35
|
+
# ===Example
|
36
|
+
# # communicator is an authenticated FsCommunicator object
|
37
|
+
# # Request a person with no assertions, only the version.
|
38
|
+
# p = communicator.familytree_v2.person :me, :names => 'none', :genders => 'none', :events => 'none'
|
39
|
+
#
|
40
|
+
# p.version # => '90194378772'
|
41
|
+
# p.id # => 'KW3B-NNM'
|
42
|
+
def person(id, options = {})
|
43
|
+
id = id.to_s
|
44
|
+
if id == 'me'
|
45
|
+
url = Base + 'person'
|
46
|
+
else
|
47
|
+
url = Base + 'person/' + id
|
48
|
+
end
|
49
|
+
url += "?"+FsUtils.querystring_from_hash(options) unless options.empty?
|
50
|
+
response = @fs_communicator.get(url)
|
51
|
+
familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
|
52
|
+
person = familytree.persons.find{|p| p.requestedId == id }
|
53
|
+
person ||= familytree.persons.first if id == 'me'
|
54
|
+
person
|
55
|
+
end
|
56
|
+
|
57
|
+
def save_person(person)
|
58
|
+
if person.id.nil?
|
59
|
+
url = Base + 'person'
|
60
|
+
else
|
61
|
+
url = Base + 'person/' + person.id
|
62
|
+
end
|
63
|
+
familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.new
|
64
|
+
familytree.persons = [person]
|
65
|
+
response = @fs_communicator.post(url,familytree.to_json)
|
66
|
+
res_familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
|
67
|
+
person = res_familytree.persons.first
|
68
|
+
return person
|
69
|
+
end
|
70
|
+
|
71
|
+
# ====Params
|
72
|
+
# <tt>search_params</tt> - A hash of search parameters matching API doc
|
73
|
+
def search(search_params)
|
74
|
+
url = Base + 'search'
|
75
|
+
url += "?" + FsUtils.querystring_from_hash(search_params) unless search_params.empty?
|
76
|
+
response = @fs_communicator.get(url)
|
77
|
+
familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
|
78
|
+
# require 'pp'
|
79
|
+
# pp familytree
|
80
|
+
familytree.searches[0]
|
81
|
+
end
|
82
|
+
|
83
|
+
# ====Params
|
84
|
+
# * <tt>base_id</tt> - The root person for creating the relationship
|
85
|
+
# * <tt>options</tt> - Should include either :parent, :spouse, or :child. :lineage and :event is optional
|
86
|
+
#
|
87
|
+
# :lineage can be set to the following values:
|
88
|
+
# * 'Biological'
|
89
|
+
# * 'Adoptive'
|
90
|
+
# * 'Foster'
|
91
|
+
# * 'Guardianship'
|
92
|
+
# * 'Step'
|
93
|
+
# * 'Other'
|
94
|
+
#
|
95
|
+
# :event should be a hash with the following values
|
96
|
+
# ** :type - "Marriage", etc. (REQUIRED)
|
97
|
+
# ** :place - "Utah, United States" (optional)
|
98
|
+
# ** :date - "Nov 2009"
|
99
|
+
#
|
100
|
+
# :ordinance should be a hash with the following values
|
101
|
+
# ** :type - "Sealing_to_Spouse", etc. (REQUIRED)
|
102
|
+
# ** :place - "Utah, United States" (optional)
|
103
|
+
# ** :date - "Nov 2009"
|
104
|
+
# ** :temple - 'SLAKE'
|
105
|
+
#
|
106
|
+
# If the :lineage is set, the parent-child relationships will be written via a characteristic.
|
107
|
+
# Otherwise, an exists assertion will be created to just establish the relationship.
|
108
|
+
# ====Example
|
109
|
+
#
|
110
|
+
# communicator.familytree_v2.write_relationship 'KWQS-BBQ', :parent => 'KWQS-BBT', :lineage => 'Biological'
|
111
|
+
# communicator.familytree_v2.write_relationship 'KWQS-BBQ', :parent => 'KWQS-BBT', :lineage => 'Adoptive'
|
112
|
+
# communicator.familytree_v2.write_relationship 'KWQS-BBQ', :spouse => 'KWRT-BBZ', :event => {:type => 'Marriage', :date => '15 Aug 1987', :place => 'Utah, United States'}
|
113
|
+
def write_relationship(base_id,options)
|
114
|
+
|
115
|
+
relationship_type = get_relationship_type(options)
|
116
|
+
with_id = options[relationship_type.to_sym]
|
117
|
+
|
118
|
+
url = "#{Base}person/#{base_id}/#{relationship_type}/#{with_id}"
|
119
|
+
|
120
|
+
# Get the existing person/relationship or create a new person
|
121
|
+
unless person = relationship(base_id,options)
|
122
|
+
person = Org::Familysearch::Ws::Familytree::V2::Schema::Person.new
|
123
|
+
person.id = base_id
|
124
|
+
end
|
125
|
+
|
126
|
+
# Add the relationship to the person with all of the correct options
|
127
|
+
r_options = {:type => relationship_type, :with => with_id}
|
128
|
+
r_options[:event] = options[:event] if options[:event]
|
129
|
+
r_options[:ordinance] = options[:ordinance] if options[:ordinance]
|
130
|
+
r_options[:lineage] = options[:lineage] if options[:lineage]
|
131
|
+
person.create_relationship r_options
|
132
|
+
|
133
|
+
# Create the payload
|
134
|
+
familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.new
|
135
|
+
familytree.persons = [person]
|
136
|
+
|
137
|
+
# Post the response and return the resulting person/relationship record from response
|
138
|
+
response = @fs_communicator.post(url,familytree.to_json)
|
139
|
+
res_familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(response.body)
|
140
|
+
person = res_familytree.persons.first
|
141
|
+
return person
|
142
|
+
end
|
143
|
+
|
144
|
+
# ====Params
|
145
|
+
# * <tt>base_id</tt> - The root person for creating the relationship
|
146
|
+
# * <tt>options</tt> - Should include either :parent, :spouse, or :child. :lineage and :event is optional
|
147
|
+
#
|
148
|
+
# If the :lineage is set, the parent-child relationships will be written via a characteristic.
|
149
|
+
# Otherwise, an exists assertion will be created to just establish the relationship.
|
150
|
+
# ====Example
|
151
|
+
#
|
152
|
+
# communicator.familytree_v2.relationship 'KWQS-BBQ', :parent => 'KWQS-BBT'
|
153
|
+
# communicator.familytree_v2.relationship 'KWQS-BBQ', :parent => 'KWQS-BBT'
|
154
|
+
def relationship(base_id,options)
|
155
|
+
r_type = get_relationship_type(options)
|
156
|
+
with_id = options[r_type.to_sym]
|
157
|
+
url = "#{Base}person/#{base_id}/#{r_type}/#{with_id}"
|
158
|
+
res = @fs_communicator.get(url)
|
159
|
+
if res.code == '404'
|
160
|
+
return nil
|
161
|
+
else
|
162
|
+
familytree = Org::Familysearch::Ws::Familytree::V2::Schema::FamilyTree.from_json JSON.parse(res.body)
|
163
|
+
person = familytree.persons.find{|p|p.id == base_id}
|
164
|
+
return person
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
private
|
169
|
+
#options will either have a :parent, :child, or :spouse key. We need to find which one
|
170
|
+
def get_relationship_type(options)
|
171
|
+
keys = options.keys.collect{|k|k.to_s}
|
172
|
+
key = keys.find{|k| ['parent','child','spouse'].include? k}
|
173
|
+
key
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
# Mix in the module so that the fs_familytree_v1 can be called
|
180
|
+
class FsCommunicator
|
181
|
+
include FamilytreeV2
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
module Org::Familysearch::Ws::Familytree::V2::Schema
|
187
|
+
|
188
|
+
class GenderAssertion
|
189
|
+
def add_value(value)
|
190
|
+
self.value = GenderValue.new
|
191
|
+
self.value.type = value
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
class NameForm
|
196
|
+
def set_name(name)
|
197
|
+
split_pieces = name.match(/(.*)\/(.*)\//)
|
198
|
+
# if there is a name like John Jacob /Felch/, split to name pieces, otherwise use fullText
|
199
|
+
if split_pieces
|
200
|
+
given_pieces = split_pieces[1]
|
201
|
+
family_pieces = split_pieces[2]
|
202
|
+
self.pieces = given_pieces.split(" ").collect do |piece|
|
203
|
+
p = NamePiece.new
|
204
|
+
p.type = "Given"
|
205
|
+
p.postdelimiters = " "
|
206
|
+
p.value = piece
|
207
|
+
p
|
208
|
+
end
|
209
|
+
self.pieces = self.pieces + family_pieces.split(" ").collect do |piece|
|
210
|
+
p = NamePiece.new
|
211
|
+
p.type = "Family"
|
212
|
+
p.predelimiters = ""
|
213
|
+
p.value = piece
|
214
|
+
p
|
215
|
+
end
|
216
|
+
else
|
217
|
+
self.fullText = name
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def buildFullText
|
222
|
+
self.pieces.collect{|piece| "#{piece.predelimiters}#{piece.value}#{piece.postdelimiters}"}.join('')
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
class NameValue
|
227
|
+
def add_form(value)
|
228
|
+
self.forms = []
|
229
|
+
f = NameForm.new
|
230
|
+
f.set_name(value)
|
231
|
+
self.forms << f
|
232
|
+
end
|
233
|
+
|
234
|
+
end
|
235
|
+
|
236
|
+
class NameAssertion
|
237
|
+
def add_value(value)
|
238
|
+
self.value = NameValue.new
|
239
|
+
self.value.add_form(value)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class EventValue
|
244
|
+
def add_date(value)
|
245
|
+
self.date = GenDate.new
|
246
|
+
self.date.original = value
|
247
|
+
end
|
248
|
+
|
249
|
+
def add_place(value)
|
250
|
+
self.place = Place.new
|
251
|
+
self.place.original = value
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
class EventAssertion
|
256
|
+
# ====Params
|
257
|
+
# * <tt>options</tt> - requires a :type option and accepts an (optional) :date and :place option
|
258
|
+
#
|
259
|
+
# ====Example
|
260
|
+
#
|
261
|
+
# person.add_birth :date => '12 Aug 1902', :place => 'United States'
|
262
|
+
def add_value(options)
|
263
|
+
raise ArgumentError, "missing option[:type]" if options[:type].nil?
|
264
|
+
self.value = EventValue.new
|
265
|
+
self.value.type = options[:type]
|
266
|
+
self.value.add_date(options[:date]) if options[:date]
|
267
|
+
self.value.add_place(options[:place]) if options[:place]
|
268
|
+
end
|
269
|
+
|
270
|
+
# To make porting code from v1 to v2 easier, date will reference
|
271
|
+
# value.date
|
272
|
+
def date
|
273
|
+
value.date
|
274
|
+
end
|
275
|
+
|
276
|
+
# To make porting code from v1 to v2 easier, date will reference
|
277
|
+
# value.date
|
278
|
+
def place
|
279
|
+
value.place
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
class OrdinanceValue
|
284
|
+
|
285
|
+
def add_date(value)
|
286
|
+
self.date = GenDate.new
|
287
|
+
self.date.original = value
|
288
|
+
end
|
289
|
+
|
290
|
+
def add_place(value)
|
291
|
+
self.place = Place.new
|
292
|
+
self.place.original = value
|
293
|
+
end
|
294
|
+
|
295
|
+
def add_mother(mother_id)
|
296
|
+
add_parent('Female',mother_id)
|
297
|
+
end
|
298
|
+
|
299
|
+
def add_father(father_id)
|
300
|
+
add_parent('Male',father_id)
|
301
|
+
end
|
302
|
+
|
303
|
+
def add_parent(gender, id)
|
304
|
+
add_parents!
|
305
|
+
parent = PersonReference.new
|
306
|
+
parent.id = id
|
307
|
+
parent.gender = gender
|
308
|
+
self.parents << parent
|
309
|
+
end
|
310
|
+
|
311
|
+
private
|
312
|
+
def add_parents!
|
313
|
+
self.parents ||= []
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|
317
|
+
|
318
|
+
class OrdinanceAssertion
|
319
|
+
|
320
|
+
def add_value(options)
|
321
|
+
raise ArgumentError, "missing option[:type]" if options[:type].nil?
|
322
|
+
raise ArgumentError, "missing option[:place]" if options[:place].nil?
|
323
|
+
self.value = OrdinanceValue.new
|
324
|
+
self.value.type = options[:type]
|
325
|
+
self.value.add_date(options[:date]) if options[:date]
|
326
|
+
self.value.add_place(options[:place]) if options[:place]
|
327
|
+
self.value.temple = options[:temple] if options[:temple]
|
328
|
+
if options[:type] == OrdinanceType::Sealing_to_Parents
|
329
|
+
self.value.add_mother(options[:mother])
|
330
|
+
self.value.add_father(options[:father])
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
class PersonAssertions
|
336
|
+
def add_gender(value)
|
337
|
+
self.genders ||= []
|
338
|
+
g = GenderAssertion.new
|
339
|
+
g.add_value(value)
|
340
|
+
self.genders << g
|
341
|
+
end
|
342
|
+
|
343
|
+
def add_name(value)
|
344
|
+
self.names ||= []
|
345
|
+
n = NameAssertion.new
|
346
|
+
n.add_value(value)
|
347
|
+
self.names << n
|
348
|
+
end
|
349
|
+
|
350
|
+
def add_event(options)
|
351
|
+
self.events ||= []
|
352
|
+
e = EventAssertion.new
|
353
|
+
e.add_value(options)
|
354
|
+
self.events << e
|
355
|
+
end
|
356
|
+
|
357
|
+
def add_ordinance(options)
|
358
|
+
self.ordinances ||= []
|
359
|
+
o = OrdinanceAssertion.new
|
360
|
+
o.add_value(options)
|
361
|
+
self.ordinances << o
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
class CharacteristicAssertion
|
366
|
+
# ====Params
|
367
|
+
# * <tt>options</tt> - same as RelationshipAssertions#add_characteristic
|
368
|
+
def add_value(options)
|
369
|
+
self.value = CharacteristicValue.new
|
370
|
+
self.value.type = options[:type]
|
371
|
+
self.value.lineage = options[:lineage] if options[:lineage]
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
class ExistsAssertion
|
376
|
+
def add_value
|
377
|
+
self.value = ExistsValue.new
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
class RelationshipAssertions
|
382
|
+
# ====Params
|
383
|
+
# * <tt>options</tt> - :type ('Lineage' or valid CharacteristicType), :lineage => 'Biological', etc.
|
384
|
+
def add_characteristic(options)
|
385
|
+
self.characteristics ||= []
|
386
|
+
characteristic = CharacteristicAssertion.new
|
387
|
+
characteristic.add_value(options)
|
388
|
+
self.characteristics << characteristic
|
389
|
+
end
|
390
|
+
|
391
|
+
# ====Params
|
392
|
+
# * <tt>options</tt> - Accepts the following options
|
393
|
+
# ** :type - 'Marriage', etc. REQUIRED
|
394
|
+
# ** :date - 'Utah, United States' (optional)
|
395
|
+
# ** :place - '16 Nov 1987' (optional)
|
396
|
+
def add_event(options)
|
397
|
+
self.events ||= []
|
398
|
+
event = EventAssertion.new
|
399
|
+
event.add_value(options)
|
400
|
+
self.events << event
|
401
|
+
end
|
402
|
+
|
403
|
+
# ====Params
|
404
|
+
# * <tt>options</tt> - Accepts the following options
|
405
|
+
# ** :type - 'Sealing_to_Spouse', etc. REQUIRED
|
406
|
+
# ** :date - 'Utah, United States' (optional)
|
407
|
+
# ** :place - '16 Nov 1987' (optional)
|
408
|
+
# ** :temple - 'SLAKE'
|
409
|
+
def add_ordinance(options)
|
410
|
+
self.ordinances ||= []
|
411
|
+
ordinance = OrdinanceAssertion.new
|
412
|
+
ordinance.add_value(options)
|
413
|
+
self.ordinances << ordinance
|
414
|
+
end
|
415
|
+
|
416
|
+
def add_exists
|
417
|
+
self.exists ||= []
|
418
|
+
exist = ExistsAssertion.new
|
419
|
+
exist.add_value
|
420
|
+
self.exists << exist
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
class Relationship
|
425
|
+
def add_lineage_characteristic(lineage)
|
426
|
+
add_assertions!
|
427
|
+
self.assertions.add_characteristic(:type => 'Lineage', :lineage => lineage)
|
428
|
+
end
|
429
|
+
|
430
|
+
def add_exists
|
431
|
+
add_assertions!
|
432
|
+
self.assertions.add_exists
|
433
|
+
end
|
434
|
+
|
435
|
+
# ====Params
|
436
|
+
# * <tt>event_hash</tt> - Accepts the following options
|
437
|
+
# ** :type - 'Marriage', etc. REQUIRED
|
438
|
+
# ** :date - 'Utah, United States' (optional)
|
439
|
+
# ** :place - '16 Nov 1987' (optional)
|
440
|
+
def add_event(event_hash)
|
441
|
+
add_assertions!
|
442
|
+
self.assertions.add_event(event_hash)
|
443
|
+
end
|
444
|
+
|
445
|
+
# ====Params
|
446
|
+
# * <tt>ordinance_hash</tt> - Accepts the following options
|
447
|
+
# ** :type - 'Sealing_to_Spouse', etc. REQUIRED
|
448
|
+
# ** :date - 'Utah, United States' (optional)
|
449
|
+
# ** :place - '16 Nov 1987' (optional)
|
450
|
+
# ** :temple - 'SLAKE'
|
451
|
+
def add_ordinance(ordinance_hash)
|
452
|
+
add_assertions!
|
453
|
+
self.assertions.add_ordinance(ordinance_hash)
|
454
|
+
end
|
455
|
+
|
456
|
+
private
|
457
|
+
def add_assertions!
|
458
|
+
self.assertions ||= RelationshipAssertions.new
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
class PersonRelationships
|
463
|
+
def initialize
|
464
|
+
@parents = []
|
465
|
+
@spouses = []
|
466
|
+
@children = []
|
467
|
+
end
|
468
|
+
|
469
|
+
# ====Params
|
470
|
+
# * <tt>options</tt> - requires the following:
|
471
|
+
# ** :type - 'parent', 'child', 'spouse'
|
472
|
+
# ** :with - ID of the person with whom you are making the relationship
|
473
|
+
# ** :lineage (optional) - 'Biological', 'Adoptive', etc.
|
474
|
+
# ** :event - a hash with values {:type => 'Marriage', :date => '15 Nov 2007', :place => 'Utah, United States'}
|
475
|
+
# ** :ordinance - a hash with values {:date => '15 Nov 2007', :temple => 'SLAKE', :place => 'Utah, United States', :type => "Sealing_to_Spouse"}
|
476
|
+
def add_relationship(options)
|
477
|
+
g_command = get_command(options[:type])
|
478
|
+
relationship = self.send(g_command.to_sym).find{|r|r.id == options[:with]}
|
479
|
+
if relationship.nil?
|
480
|
+
relationship = Relationship.new
|
481
|
+
relationship.id = options[:with]
|
482
|
+
end
|
483
|
+
if options[:lineage]
|
484
|
+
relationship.add_lineage_characteristic(options[:lineage]) if options[:lineage]
|
485
|
+
else
|
486
|
+
relationship.add_exists
|
487
|
+
end
|
488
|
+
if options[:event]
|
489
|
+
relationship.add_event(options[:event])
|
490
|
+
end
|
491
|
+
if options[:ordinance]
|
492
|
+
relationship.add_ordinance(options[:ordinance])
|
493
|
+
end
|
494
|
+
s_command = set_command(options[:type])
|
495
|
+
self.send(s_command.to_sym,[relationship])
|
496
|
+
end
|
497
|
+
|
498
|
+
# Overriding the Enunciate code because of a bug (parents, spouses, and children were not pluralized)
|
499
|
+
# the json hash for this PersonRelationships
|
500
|
+
def to_jaxb_json_hash
|
501
|
+
_h = {}
|
502
|
+
if !parents.nil?
|
503
|
+
_ha = Array.new
|
504
|
+
parents.each { | _item | _ha.push _item.to_jaxb_json_hash }
|
505
|
+
_h['parents'] = _ha
|
506
|
+
end
|
507
|
+
if !spouses.nil?
|
508
|
+
_ha = Array.new
|
509
|
+
spouses.each { | _item | _ha.push _item.to_jaxb_json_hash }
|
510
|
+
_h['spouses'] = _ha
|
511
|
+
end
|
512
|
+
if !children.nil?
|
513
|
+
_ha = Array.new
|
514
|
+
children.each { | _item | _ha.push _item.to_jaxb_json_hash }
|
515
|
+
_h['children'] = _ha
|
516
|
+
end
|
517
|
+
return _h
|
518
|
+
end
|
519
|
+
|
520
|
+
# Overriding the Enunciate code because of a bug
|
521
|
+
#initializes this PersonRelationships with a json hash
|
522
|
+
def init_jaxb_json_hash(_o)
|
523
|
+
if !_o['parents'].nil?
|
524
|
+
@parents = Array.new
|
525
|
+
_oa = _o['parents']
|
526
|
+
_oa.each { | _item | @parents.push Org::Familysearch::Ws::Familytree::V2::Schema::Relationship.from_json(_item) }
|
527
|
+
end
|
528
|
+
if !_o['spouses'].nil?
|
529
|
+
@spouses = Array.new
|
530
|
+
_oa = _o['spouses']
|
531
|
+
_oa.each { | _item | @spouses.push Org::Familysearch::Ws::Familytree::V2::Schema::Relationship.from_json(_item) }
|
532
|
+
end
|
533
|
+
if !_o['children'].nil?
|
534
|
+
@children = Array.new
|
535
|
+
_oa = _o['children']
|
536
|
+
_oa.each { | _item | @children.push Org::Familysearch::Ws::Familytree::V2::Schema::Relationship.from_json(_item) }
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
540
|
+
private
|
541
|
+
def get_command(type)
|
542
|
+
(type == 'child') ? 'children' : "#{type}s"
|
543
|
+
end
|
544
|
+
|
545
|
+
def set_command(type)
|
546
|
+
get_command(type)+"="
|
547
|
+
end
|
548
|
+
end
|
549
|
+
|
550
|
+
class Person
|
551
|
+
|
552
|
+
def full_names
|
553
|
+
if assertions && assertions.names
|
554
|
+
return assertions.names.collect do |name|
|
555
|
+
(name.value.forms[0].fullText.nil?) ? name.value.forms[0].buildFullText : name.value.forms[0].fullText
|
556
|
+
end
|
557
|
+
else
|
558
|
+
[]
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
def full_name
|
563
|
+
self.full_names.first
|
564
|
+
end
|
565
|
+
|
566
|
+
def gender
|
567
|
+
if assertions && assertions.genders && assertions.genders[0] && assertions.genders[0].value
|
568
|
+
assertions.genders[0].value.type
|
569
|
+
else
|
570
|
+
nil
|
571
|
+
end
|
572
|
+
end
|
573
|
+
|
574
|
+
# Convenience method for adding the gender.
|
575
|
+
#
|
576
|
+
# ====Params
|
577
|
+
# <tt>value</tt> - 'Male' or 'Female'
|
578
|
+
def add_gender(value)
|
579
|
+
add_assertions!
|
580
|
+
assertions.add_gender(value)
|
581
|
+
end
|
582
|
+
|
583
|
+
# Convenience method for adding a name. It fills in the necessary
|
584
|
+
# structure underneath to create the name.
|
585
|
+
#
|
586
|
+
# ====Params
|
587
|
+
# <tt>value</tt> - the name to be added
|
588
|
+
#
|
589
|
+
# ====Example
|
590
|
+
#
|
591
|
+
# person.add_name 'Parker Felch' # Sets the fullText to "Parker Felch"
|
592
|
+
# person.add_name 'Parker Jones /Felch/' # Does not set the fullText, but sets the name pieces.
|
593
|
+
def add_name(value)
|
594
|
+
add_assertions!
|
595
|
+
assertions.add_name(value)
|
596
|
+
end
|
597
|
+
|
598
|
+
def births
|
599
|
+
select_events('Birth')
|
600
|
+
end
|
601
|
+
|
602
|
+
# It should return the selected birth assertion unless it is
|
603
|
+
# not set in which case it will return the first
|
604
|
+
def birth
|
605
|
+
birth = births.find{|b|!b.selected.nil?}
|
606
|
+
birth ||= births[0]
|
607
|
+
birth
|
608
|
+
end
|
609
|
+
|
610
|
+
def deaths
|
611
|
+
select_events('Death')
|
612
|
+
end
|
613
|
+
|
614
|
+
# It should return the selected death assertion unless it is
|
615
|
+
# not set in which case it will return the first
|
616
|
+
def death
|
617
|
+
death = deaths.find{|b|!b.selected.nil?}
|
618
|
+
death ||= deaths[0]
|
619
|
+
death
|
620
|
+
end
|
621
|
+
|
622
|
+
# Add an event with type of Birth
|
623
|
+
#
|
624
|
+
# ====Params
|
625
|
+
# * <tt>options</tt> - accepts a :date and :place option
|
626
|
+
#
|
627
|
+
# ====Example
|
628
|
+
#
|
629
|
+
# person.add_birth :date => '12 Aug 1902', :place => 'United States'
|
630
|
+
def add_birth(options)
|
631
|
+
add_assertions!
|
632
|
+
options[:type] = 'Birth'
|
633
|
+
assertions.add_event(options)
|
634
|
+
end
|
635
|
+
|
636
|
+
# Add an event with type of Birth
|
637
|
+
#
|
638
|
+
# ====Params
|
639
|
+
# * <tt>options</tt> - accepts a :date and :place option
|
640
|
+
#
|
641
|
+
# ====Example
|
642
|
+
#
|
643
|
+
# person.add_birth :date => '12 Aug 1902', :place => 'United States'
|
644
|
+
def add_death(options)
|
645
|
+
add_assertions!
|
646
|
+
options[:type] = 'Death'
|
647
|
+
assertions.add_event(options)
|
648
|
+
end
|
649
|
+
|
650
|
+
def baptisms
|
651
|
+
select_ordinances('Baptism')
|
652
|
+
end
|
653
|
+
|
654
|
+
def confirmations
|
655
|
+
select_ordinances('Confirmation')
|
656
|
+
end
|
657
|
+
|
658
|
+
def initiatories
|
659
|
+
select_ordinances('Initiatory')
|
660
|
+
end
|
661
|
+
|
662
|
+
def endowments
|
663
|
+
select_ordinances('Endowment')
|
664
|
+
end
|
665
|
+
|
666
|
+
def sealing_to_parents
|
667
|
+
select_ordinances(OrdinanceType::Sealing_to_Parents)
|
668
|
+
end
|
669
|
+
|
670
|
+
def sealing_to_spouses(id)
|
671
|
+
select_relationship_ordinances(:relationship_type => 'spouse', :id => id, :type => OrdinanceType::Sealing_to_Spouse)
|
672
|
+
end
|
673
|
+
|
674
|
+
# Add a baptism ordinance
|
675
|
+
#
|
676
|
+
# ====Params
|
677
|
+
# * <tt>options</tt> - accepts a :date, :place, and :temple option
|
678
|
+
#
|
679
|
+
# ====Example
|
680
|
+
#
|
681
|
+
# person.add_baptism :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
|
682
|
+
def add_baptism(options)
|
683
|
+
add_assertions!
|
684
|
+
options[:type] = 'Baptism'
|
685
|
+
assertions.add_ordinance(options)
|
686
|
+
end
|
687
|
+
|
688
|
+
# Add a confirmation ordinance
|
689
|
+
#
|
690
|
+
# ====Params
|
691
|
+
# * <tt>options</tt> - accepts a :date, :place, and :temple option
|
692
|
+
#
|
693
|
+
# ====Example
|
694
|
+
#
|
695
|
+
# person.add_confirmation :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
|
696
|
+
def add_confirmation(options)
|
697
|
+
add_assertions!
|
698
|
+
options[:type] = 'Confirmation'
|
699
|
+
assertions.add_ordinance(options)
|
700
|
+
end
|
701
|
+
|
702
|
+
# Add a initiatory ordinance
|
703
|
+
#
|
704
|
+
# ====Params
|
705
|
+
# * <tt>options</tt> - accepts a :date, :place, and :temple option
|
706
|
+
#
|
707
|
+
# ====Example
|
708
|
+
#
|
709
|
+
# person.add_initiatory :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
|
710
|
+
def add_initiatory(options)
|
711
|
+
add_assertions!
|
712
|
+
options[:type] = 'Initiatory'
|
713
|
+
assertions.add_ordinance(options)
|
714
|
+
end
|
715
|
+
|
716
|
+
# Add a endowment ordinance
|
717
|
+
#
|
718
|
+
# ====Params
|
719
|
+
# * <tt>options</tt> - accepts a :date, :place, and :temple option
|
720
|
+
#
|
721
|
+
# ====Example
|
722
|
+
#
|
723
|
+
# person.add_endowment :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
|
724
|
+
def add_endowment(options)
|
725
|
+
add_assertions!
|
726
|
+
options[:type] = 'Endowment'
|
727
|
+
assertions.add_ordinance(options)
|
728
|
+
end
|
729
|
+
|
730
|
+
# Add a sealing to parents ordinance
|
731
|
+
#
|
732
|
+
# ====Params
|
733
|
+
# * <tt>options</tt> - accepts a :date, :place, :temple, :mother, and :father option
|
734
|
+
#
|
735
|
+
# ====Example
|
736
|
+
#
|
737
|
+
# person.add_sealing_to_parents :date => '14 Aug 2009', :temple => 'SGEOR', :place => 'Salt Lake City, Utah'
|
738
|
+
def add_sealing_to_parents(options)
|
739
|
+
raise ArgumentError, ":mother option is required" if options[:mother].nil?
|
740
|
+
raise ArgumentError, ":father option is required" if options[:father].nil?
|
741
|
+
add_assertions!
|
742
|
+
options[:type] = OrdinanceType::Sealing_to_Parents
|
743
|
+
assertions.add_ordinance(options)
|
744
|
+
end
|
745
|
+
|
746
|
+
# This method should really only be called from FamilytreeV2::Communicator#write_relationships
|
747
|
+
#
|
748
|
+
# ====Params
|
749
|
+
# * <tt>options</tt> - requires the following:
|
750
|
+
# ** :type - 'parent', 'child', 'spouse'
|
751
|
+
# ** :with - ID of the person with whom you are making the relationship
|
752
|
+
# ** :lineage (optional) - 'Biological', 'Adoptive', etc.
|
753
|
+
# ** :event - a hash with values {:type => 'Marriage', :date => '15 Nov 2007', :place => 'Utah, United States'}
|
754
|
+
def create_relationship(options)
|
755
|
+
raise ArgumentError, ":type option is required" if options[:type].nil?
|
756
|
+
raise ArgumentError, ":with option is required" if options[:with].nil?
|
757
|
+
add_relationships!
|
758
|
+
self.relationships.add_relationship(options)
|
759
|
+
end
|
760
|
+
|
761
|
+
private
|
762
|
+
|
763
|
+
def add_relationships!
|
764
|
+
self.relationships ||= PersonRelationships.new
|
765
|
+
end
|
766
|
+
|
767
|
+
def add_assertions!
|
768
|
+
if assertions.nil?
|
769
|
+
self.assertions = PersonAssertions.new
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
def select_events(type)
|
774
|
+
if assertions && assertions.events
|
775
|
+
assertions.events.select{|e| e.value.type == type}
|
776
|
+
else
|
777
|
+
[]
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
def select_ordinances(type)
|
782
|
+
if assertions && assertions.ordinances
|
783
|
+
assertions.ordinances.select{|e| e.value.type == type}
|
784
|
+
else
|
785
|
+
[]
|
786
|
+
end
|
787
|
+
end
|
788
|
+
|
789
|
+
# only ordinance type is Sealing_to_Spouse
|
790
|
+
def select_relationship_ordinances(options)
|
791
|
+
raise ArgumentError, ":id required" if options[:id].nil?
|
792
|
+
if self.relationships
|
793
|
+
spouse_relationship = self.relationships.spouses.find{|s|s.id == options[:id]}
|
794
|
+
if spouse_relationship && spouse_relationship.assertions && spouse_relationship.assertions.ordinances
|
795
|
+
spouse_relationship.assertions.ordinances
|
796
|
+
else
|
797
|
+
[]
|
798
|
+
end
|
799
|
+
end
|
800
|
+
end
|
801
|
+
|
802
|
+
end
|
803
|
+
|
804
|
+
class SearchPerson
|
805
|
+
alias :name :full_name
|
806
|
+
def events
|
807
|
+
(assertions && assertions.events) ? assertions.events : []
|
808
|
+
end
|
809
|
+
|
810
|
+
# Always will return nil. Method is here for v1 backwards compatibility
|
811
|
+
def marriage
|
812
|
+
nil
|
813
|
+
end
|
814
|
+
end
|
815
|
+
|
816
|
+
class SearchResult
|
817
|
+
alias :ref :id
|
818
|
+
|
819
|
+
def father
|
820
|
+
parents.find{|p|p.gender == 'Male'}
|
821
|
+
end
|
822
|
+
|
823
|
+
def mother
|
824
|
+
parents.find{|p|p.gender == 'Female'}
|
825
|
+
end
|
826
|
+
end
|
827
|
+
end
|