genealogy 0.3.0 → 0.3.9
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.
- checksums.yaml +8 -8
- data/lib/genealogy/alter_methods.rb +77 -13
- data/lib/genealogy/constants.rb +22 -1
- data/lib/genealogy/genealogy.rb +10 -7
- data/lib/genealogy/query_methods.rb +146 -17
- data/lib/genealogy/spouse_methods.rb +15 -10
- data/lib/genealogy/version.rb +1 -1
- metadata +17 -3
checksums.yaml
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
!binary "U0hBMQ==":
|
|
3
3
|
metadata.gz: !binary |-
|
|
4
|
-
|
|
4
|
+
YzJjYzM4NzU0NWU4OWI3N2I1OWUzZWU5OGI3M2VlOTc3NTU5MGU1Yg==
|
|
5
5
|
data.tar.gz: !binary |-
|
|
6
|
-
|
|
6
|
+
ZWRhODI1YjMxMjA1NDA3MTQ3ZGNhN2NhNDgyOTEyMDQ2ZGY5MmIyZA==
|
|
7
7
|
!binary "U0hBNTEy":
|
|
8
8
|
metadata.gz: !binary |-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
ZmNiN2MwOTJkN2E2NmExNmMyY2MzYWI5ZWJkMTkwNjE2YTJkNzJlMzM4MDll
|
|
10
|
+
MTE3MTM0YmI1NWM0N2U3YzA0NDAxYzg1ZDMxNTllMzZkYzJmMTMzMTc1NTc3
|
|
11
|
+
MTgyNTMyM2FkZTlkMGY1MGFhZDllM2Q2OWU0MzNlNTc1ZjJhMDQ=
|
|
12
12
|
data.tar.gz: !binary |-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
MmY0Yzc1M2FjY2ZjYjJhZWFlZTcyMDMwYmFjOWIxNmQwYzAyMjAxM2E1N2Nl
|
|
14
|
+
ZTFiYjQzYzBmMzRlNzBkMmI4NWQxY2JkMDg2OGYzZjg4MTdmOWY4ZDBkZTRm
|
|
15
|
+
N2QyNDM5OWY2Y2RhYWNlNjdkZjBjNTljNWEyMDJhMjdkMzExNzU=
|
|
@@ -8,7 +8,7 @@ module Genealogy
|
|
|
8
8
|
# add method
|
|
9
9
|
define_method "add_#{parent}" do |relative|
|
|
10
10
|
unless relative.nil?
|
|
11
|
-
raise IncompatibleObjectException, "
|
|
11
|
+
raise IncompatibleObjectException, "Both linked objects must be instances of class with genealogy enabled. Got classes #{relative.class} and #{self.genealogy_class}" unless relative.class.respond_to?(:genealogy_enabled)
|
|
12
12
|
incompatible_parents = self.offspring | self.siblings.to_a | [self]
|
|
13
13
|
raise IncompatibleRelationshipException, "#{relative} can't be #{parent} of #{self}" if incompatible_parents.include? relative
|
|
14
14
|
raise WrongSexException, "Can't add a #{relative.sex} #{parent}" unless (parent == :father and relative.is_male?) or (parent == :mother and relative.is_female?)
|
|
@@ -45,13 +45,13 @@ module Genealogy
|
|
|
45
45
|
[:father, :mother].each do |parent|
|
|
46
46
|
[:father, :mother].each do |grandparent|
|
|
47
47
|
# add one
|
|
48
|
-
define_method "add_#{Genealogy::
|
|
48
|
+
define_method "add_#{Genealogy::PARENT2LINEAGE[parent]}_grand#{grandparent}" do |relative|
|
|
49
49
|
raise IncompatibleRelationshipException, "#{self} can't be grand#{grandparent} of itself" if relative == self
|
|
50
50
|
raise_if_gap_on(parent)
|
|
51
51
|
send(parent).send("add_#{grandparent}",relative)
|
|
52
52
|
end
|
|
53
53
|
# remove one
|
|
54
|
-
define_method "remove_#{Genealogy::
|
|
54
|
+
define_method "remove_#{Genealogy::PARENT2LINEAGE[parent]}_grand#{grandparent}" do
|
|
55
55
|
raise_if_gap_on(parent)
|
|
56
56
|
send(parent).send("remove_#{grandparent}")
|
|
57
57
|
end
|
|
@@ -60,12 +60,12 @@ module Genealogy
|
|
|
60
60
|
|
|
61
61
|
[:father, :mother].each do |parent|
|
|
62
62
|
# add two by lineage
|
|
63
|
-
define_method "add_#{Genealogy::
|
|
63
|
+
define_method "add_#{Genealogy::PARENT2LINEAGE[parent]}_grandparents" do |grandfather,grandmother|
|
|
64
64
|
raise_if_gap_on(parent)
|
|
65
65
|
send(parent).send("add_parents",grandfather,grandmother)
|
|
66
66
|
end
|
|
67
67
|
# remove two by lineage
|
|
68
|
-
define_method "remove_#{Genealogy::
|
|
68
|
+
define_method "remove_#{Genealogy::PARENT2LINEAGE[parent]}_grandparents" do
|
|
69
69
|
raise_if_gap_on(parent)
|
|
70
70
|
send(parent).send("remove_parents")
|
|
71
71
|
end
|
|
@@ -91,18 +91,20 @@ module Genealogy
|
|
|
91
91
|
## siblings
|
|
92
92
|
def add_siblings(*args)
|
|
93
93
|
options = args.extract_options!
|
|
94
|
-
raise LineageGapException, "Can't add siblings if both parents are nil" unless father and mother
|
|
95
94
|
raise IncompatibleRelationshipException, "Can't add an ancestor as sibling" unless (ancestors.to_a & args).empty?
|
|
96
95
|
transaction do
|
|
97
96
|
args.each do |sib|
|
|
98
97
|
case options[:half]
|
|
99
98
|
when :father
|
|
99
|
+
raise LineageGapException, "Can't add paternal halfsiblings without a father" unless father
|
|
100
100
|
sib.add_father(self.father)
|
|
101
101
|
sib.add_mother(options[:spouse]) if options[:spouse]
|
|
102
102
|
when :mother
|
|
103
|
+
raise LineageGapException, "Can't add maternal halfsiblings without a mother" unless mother
|
|
103
104
|
sib.add_father(options[:spouse]) if options[:spouse]
|
|
104
105
|
sib.add_mother(self.mother)
|
|
105
106
|
when nil
|
|
107
|
+
raise LineageGapException, "Can't add siblings without parents" unless father and mother
|
|
106
108
|
sib.add_father(self.father)
|
|
107
109
|
sib.add_mother(self.mother)
|
|
108
110
|
else
|
|
@@ -112,10 +114,20 @@ module Genealogy
|
|
|
112
114
|
end
|
|
113
115
|
end
|
|
114
116
|
|
|
115
|
-
def
|
|
116
|
-
options
|
|
117
|
+
def add_sibling(sib,options={})
|
|
118
|
+
add_siblings(sib,options)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def remove_siblings(*args)
|
|
122
|
+
options = args.extract_options!
|
|
123
|
+
|
|
124
|
+
raise WrongOptionException.new("Unknown option value: :half => #{options[:half]}.") if (options[:half] and ![:father,:mother].include?(options[:half]))
|
|
117
125
|
|
|
118
|
-
resulting_indivs =
|
|
126
|
+
resulting_indivs = if args.blank?
|
|
127
|
+
siblings(options)
|
|
128
|
+
else
|
|
129
|
+
args & siblings(options)
|
|
130
|
+
end
|
|
119
131
|
|
|
120
132
|
transaction do
|
|
121
133
|
|
|
@@ -130,12 +142,50 @@ module Genealogy
|
|
|
130
142
|
when nil
|
|
131
143
|
sib.remove_parents
|
|
132
144
|
end
|
|
133
|
-
|
|
134
145
|
end
|
|
146
|
+
|
|
135
147
|
end
|
|
136
148
|
|
|
149
|
+
!resulting_indivs.empty? #returned value must be true if self has at least a siblings to affect
|
|
150
|
+
|
|
137
151
|
end
|
|
138
152
|
|
|
153
|
+
def remove_sibling(sib,options={})
|
|
154
|
+
remove_siblings(sib,options)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
[:father, :mother].each do |parent|
|
|
158
|
+
|
|
159
|
+
# add paternal/maternal half_siblings
|
|
160
|
+
define_method "add_#{Genealogy::PARENT2LINEAGE[parent]}_half_siblings" do | *args |
|
|
161
|
+
options = args.extract_options!
|
|
162
|
+
options[:half] = parent
|
|
163
|
+
args << options
|
|
164
|
+
send("add_siblings",*args)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# add paternal/maternal half_sibling
|
|
168
|
+
define_method "add_#{Genealogy::PARENT2LINEAGE[parent]}_half_sibling" do | sib,options={} |
|
|
169
|
+
options[:half] = parent
|
|
170
|
+
send("add_sibling",sib,options)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# remove paternal/maternal half_siblings
|
|
174
|
+
define_method "remove_#{Genealogy::PARENT2LINEAGE[parent]}_half_siblings" do | *args |
|
|
175
|
+
options = args.extract_options!
|
|
176
|
+
options[:half] = parent
|
|
177
|
+
args << options
|
|
178
|
+
send("remove_siblings",*args)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# remove paternal/maternal half_sibling
|
|
182
|
+
define_method "remove_#{Genealogy::PARENT2LINEAGE[parent]}_half_sibling" do | sib,options={} |
|
|
183
|
+
options[:half] = parent
|
|
184
|
+
send("remove_sibling",sib,options)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
|
|
139
189
|
# offspring
|
|
140
190
|
def add_offspring(*args)
|
|
141
191
|
options = args.extract_options!
|
|
@@ -156,11 +206,21 @@ module Genealogy
|
|
|
156
206
|
end
|
|
157
207
|
end
|
|
158
208
|
|
|
159
|
-
def
|
|
209
|
+
def add_child(child,options={})
|
|
210
|
+
add_offspring(child,options)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def remove_offspring(*args)
|
|
214
|
+
options = args.extract_options!
|
|
160
215
|
|
|
161
216
|
raise_if_sex_undefined
|
|
162
217
|
|
|
163
|
-
resulting_indivs =
|
|
218
|
+
resulting_indivs = if args.blank?
|
|
219
|
+
offspring(options)
|
|
220
|
+
else
|
|
221
|
+
args & offspring(options)
|
|
222
|
+
end
|
|
223
|
+
|
|
164
224
|
transaction do
|
|
165
225
|
resulting_indivs.each do |child|
|
|
166
226
|
if options[:affect_spouse] == true
|
|
@@ -175,7 +235,11 @@ module Genealogy
|
|
|
175
235
|
end
|
|
176
236
|
end
|
|
177
237
|
end
|
|
178
|
-
resulting_indivs.empty?
|
|
238
|
+
!resulting_indivs.empty? #returned value must be true if self has at least a siblings to affect
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def remove_child(child,options={})
|
|
242
|
+
remove_offspring(child,options)
|
|
179
243
|
end
|
|
180
244
|
|
|
181
245
|
private
|
data/lib/genealogy/constants.rb
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
1
|
module Genealogy
|
|
2
|
-
|
|
2
|
+
PARENT2LINEAGE = { :father => :paternal, :mother => :maternal }
|
|
3
|
+
LINEAGE2PARENT = PARENT2LINEAGE.invert
|
|
4
|
+
PARENT2SEX = { :father => :male, :mother => :female }
|
|
5
|
+
SEX2PARENT = PARENT2SEX.invert
|
|
6
|
+
OPPOSITESEX = {:male => :female, :female => :male}
|
|
7
|
+
|
|
8
|
+
AKA = {
|
|
9
|
+
:father => "F",
|
|
10
|
+
:mother => "M",
|
|
11
|
+
:paternal_grandfather => "PGF",
|
|
12
|
+
:paternal_grandmother => "PGM",
|
|
13
|
+
:maternal_grandfather => "MGF",
|
|
14
|
+
:maternal_grandmother => "MGM",
|
|
15
|
+
:children => "C",
|
|
16
|
+
:siblings => "S",
|
|
17
|
+
:half_siblings => "HS",
|
|
18
|
+
:paternal_half_siblings => "PHS",
|
|
19
|
+
:maternal_half_siblings => "MHS",
|
|
20
|
+
:grandchildren => "GC",
|
|
21
|
+
:uncles_and_aunts => "U&A",
|
|
22
|
+
:nieces_and_nephews => "N&N"
|
|
23
|
+
}
|
|
3
24
|
end
|
data/lib/genealogy/genealogy.rb
CHANGED
|
@@ -19,17 +19,20 @@ module Genealogy
|
|
|
19
19
|
|
|
20
20
|
def has_parents options = {}
|
|
21
21
|
|
|
22
|
-
admitted_keys = [:sex_column, :sex_values, :father_column, :mother_column, :
|
|
22
|
+
admitted_keys = [:sex_column, :sex_values, :father_column, :mother_column, :current_spouse_column, :current_spouse]
|
|
23
23
|
check_options(options, admitted_keys) do |key, value|
|
|
24
24
|
if key == :sex_values
|
|
25
25
|
raise WrongOptionException, ":sex_values option must be an array with two char: first for male sex symbol an last for female" unless value.is_a?(Array) and value.size == 2 and value.first.to_s.size == 1 and value.last.to_s.size == 1
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
class_attribute :
|
|
30
|
-
self.
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
class_attribute :genealogy_enabled, :current_spouse_enabled, :genealogy_class
|
|
30
|
+
self.genealogy_enabled = true
|
|
31
|
+
self.current_spouse_enabled = options[:current_spouse].try(:==,true) || false
|
|
32
|
+
self.genealogy_class = self #keep track of the original extend class to prevent wrong scopes in query method in case of STI
|
|
33
|
+
|
|
34
|
+
tracked_relatives = [:father, :mother]
|
|
35
|
+
tracked_relatives << :current_spouse if current_spouse_enabled
|
|
33
36
|
|
|
34
37
|
## sex
|
|
35
38
|
# class attributes
|
|
@@ -45,7 +48,7 @@ module Genealogy
|
|
|
45
48
|
validates_format_of sex_column, :with => /[#{sex_values.join}]/
|
|
46
49
|
|
|
47
50
|
## relatives associations
|
|
48
|
-
|
|
51
|
+
tracked_relatives.each do |key|
|
|
49
52
|
# class attribute where is stored the correspondig foreign_key column name
|
|
50
53
|
class_attribute_name = "#{key}_column"
|
|
51
54
|
foreign_key = "#{key}_id"
|
|
@@ -61,7 +64,7 @@ module Genealogy
|
|
|
61
64
|
# Include instance methods and class methods
|
|
62
65
|
include Genealogy::QueryMethods
|
|
63
66
|
include Genealogy::AlterMethods
|
|
64
|
-
include Genealogy::SpouseMethods if
|
|
67
|
+
include Genealogy::SpouseMethods if current_spouse_enabled
|
|
65
68
|
|
|
66
69
|
end
|
|
67
70
|
|
|
@@ -4,10 +4,17 @@ module Genealogy
|
|
|
4
4
|
|
|
5
5
|
# parents
|
|
6
6
|
def parents
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
[father,mother]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# eligible
|
|
11
|
+
[:father, :mother].each do |parent|
|
|
12
|
+
define_method "eligible_#{parent}s" do
|
|
13
|
+
if send(parent)
|
|
14
|
+
[]
|
|
15
|
+
else
|
|
16
|
+
self.genealogy_class.send("#{Genealogy::PARENT2SEX[parent]}s") - descendants - [self]
|
|
17
|
+
end
|
|
11
18
|
end
|
|
12
19
|
end
|
|
13
20
|
|
|
@@ -16,52 +23,89 @@ module Genealogy
|
|
|
16
23
|
[:father, :mother].each do |grandparent|
|
|
17
24
|
|
|
18
25
|
# get one
|
|
19
|
-
define_method "#{Genealogy::
|
|
26
|
+
define_method "#{Genealogy::PARENT2LINEAGE[parent]}_grand#{grandparent}" do
|
|
20
27
|
send(parent) && send(parent).send(grandparent)
|
|
21
28
|
end
|
|
22
29
|
|
|
30
|
+
# eligible
|
|
31
|
+
define_method "eligible_#{Genealogy::PARENT2LINEAGE[parent]}_grand#{grandparent}s" do
|
|
32
|
+
if send(parent) and send("#{Genealogy::PARENT2LINEAGE[parent]}_grand#{grandparent}").nil?
|
|
33
|
+
send(parent).send("eligible_#{grandparent}s") - [self]
|
|
34
|
+
else
|
|
35
|
+
[]
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
23
39
|
end
|
|
24
40
|
|
|
25
41
|
# get two by lineage
|
|
26
|
-
define_method "#{Genealogy::
|
|
27
|
-
(send(parent) && send(parent).parents) || []
|
|
42
|
+
define_method "#{Genealogy::PARENT2LINEAGE[parent]}_grandparents" do
|
|
43
|
+
(send(parent) && send(parent).parents) || [nil,nil]
|
|
28
44
|
end
|
|
29
45
|
|
|
30
46
|
end
|
|
31
47
|
|
|
32
|
-
# get all
|
|
33
48
|
def grandparents
|
|
34
49
|
result = []
|
|
35
50
|
[:father, :mother].each do |parent|
|
|
36
51
|
[:father, :mother].each do |grandparent|
|
|
37
|
-
result << send("#{Genealogy::
|
|
52
|
+
result << send("#{Genealogy::PARENT2LINEAGE[parent]}_grand#{grandparent}")
|
|
38
53
|
end
|
|
39
54
|
end
|
|
40
|
-
result.compact! if result.all?{|gp| gp.nil? }
|
|
55
|
+
# result.compact! if result.all?{|gp| gp.nil? }
|
|
41
56
|
result
|
|
42
57
|
end
|
|
43
58
|
|
|
59
|
+
# offspring
|
|
44
60
|
def offspring(options = {})
|
|
45
|
-
|
|
46
61
|
if spouse = options[:spouse]
|
|
47
62
|
raise WrongSexException, "Something wrong with spouse #{spouse} gender." if spouse.sex == sex
|
|
48
63
|
end
|
|
49
64
|
case sex
|
|
50
65
|
when sex_male_value
|
|
51
|
-
|
|
66
|
+
if options.keys.include?(:spouse)
|
|
67
|
+
self.genealogy_class.find_all_by_father_id_and_mother_id(id,spouse.try(:id))
|
|
68
|
+
else
|
|
69
|
+
self.genealogy_class.find_all_by_father_id(id)
|
|
70
|
+
end
|
|
52
71
|
when sex_female_value
|
|
53
|
-
|
|
72
|
+
if options.keys.include?(:spouse)
|
|
73
|
+
self.genealogy_class.find_all_by_mother_id_and_father_id(id,spouse.try(:id))
|
|
74
|
+
else
|
|
75
|
+
self.genealogy_class.find_all_by_mother_id(id)
|
|
76
|
+
end
|
|
54
77
|
end
|
|
55
78
|
end
|
|
79
|
+
alias_method :children, :offspring
|
|
80
|
+
|
|
81
|
+
def eligible_offspring
|
|
82
|
+
self.genealogy_class.all - ancestors - offspring - siblings - [self]
|
|
83
|
+
end
|
|
84
|
+
alias_method :eligible_children, :eligible_offspring
|
|
85
|
+
|
|
86
|
+
# spouses
|
|
87
|
+
def spouses
|
|
88
|
+
parent_method = Genealogy::SEX2PARENT[Genealogy::OPPOSITESEX[sex_to_s.to_sym]]
|
|
89
|
+
offspring.collect{|child| child.send(parent_method)}.uniq
|
|
90
|
+
end
|
|
56
91
|
|
|
92
|
+
def eligible_spouses
|
|
93
|
+
self.genealogy_class.send("#{Genealogy::OPPOSITESEX[sex_to_s.to_sym]}s") - spouses
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# siblings
|
|
57
97
|
def siblings(options = {})
|
|
58
98
|
result = case options[:half]
|
|
59
|
-
when nil #
|
|
60
|
-
|
|
99
|
+
when nil # only full siblings
|
|
100
|
+
unless parents.include?(nil)
|
|
101
|
+
father.try(:offspring, :spouse => mother ).to_a
|
|
102
|
+
else
|
|
103
|
+
[]
|
|
104
|
+
end
|
|
61
105
|
when :father # common father
|
|
62
|
-
father.try(:offspring, :spouse => options[:spouse]).to_a - mother.try(:offspring).to_a
|
|
106
|
+
father.try(:offspring, options.keys.include?(:spouse) ? {:spouse => options[:spouse]} : {}).to_a - mother.try(:offspring).to_a
|
|
63
107
|
when :mother # common mother
|
|
64
|
-
mother.try(:offspring, :spouse => options[:spouse]).to_a - father.try(:offspring).to_a
|
|
108
|
+
mother.try(:offspring, options.keys.include?(:spouse) ? {:spouse => options[:spouse]} : {}).to_a - father.try(:offspring).to_a
|
|
65
109
|
when :only # only half siblings
|
|
66
110
|
siblings(:half => :include) - siblings
|
|
67
111
|
when :include # including half siblings
|
|
@@ -72,6 +116,10 @@ module Genealogy
|
|
|
72
116
|
result.uniq - [self]
|
|
73
117
|
end
|
|
74
118
|
|
|
119
|
+
def eligible_siblings
|
|
120
|
+
self.genealogy_class.all - ancestors - siblings(:half => :include) - [self]
|
|
121
|
+
end
|
|
122
|
+
|
|
75
123
|
def half_siblings
|
|
76
124
|
siblings(:half => :only)
|
|
77
125
|
# todo: inprove with option :father and :mother
|
|
@@ -85,6 +133,11 @@ module Genealogy
|
|
|
85
133
|
siblings(:half => :mother)
|
|
86
134
|
end
|
|
87
135
|
|
|
136
|
+
alias_method :eligible_half_siblings, :eligible_siblings
|
|
137
|
+
alias_method :eligible_paternal_half_siblings, :eligible_siblings
|
|
138
|
+
alias_method :eligible_maternal_half_siblings, :eligible_siblings
|
|
139
|
+
|
|
140
|
+
# ancestors
|
|
88
141
|
def ancestors
|
|
89
142
|
result = []
|
|
90
143
|
remaining = parents.to_a.compact
|
|
@@ -95,16 +148,86 @@ module Genealogy
|
|
|
95
148
|
result.uniq
|
|
96
149
|
end
|
|
97
150
|
|
|
151
|
+
# descendants
|
|
98
152
|
def descendants
|
|
99
153
|
result = []
|
|
100
154
|
remaining = offspring.to_a.compact
|
|
101
155
|
until remaining.empty?
|
|
102
156
|
result << remaining.shift
|
|
103
157
|
remaining += result.last.offspring.to_a.compact
|
|
158
|
+
# break if (remaining - result).empty? can be necessary in case of loop. Idem for ancestors method
|
|
104
159
|
end
|
|
105
160
|
result.uniq
|
|
106
161
|
end
|
|
107
162
|
|
|
163
|
+
def grandchildren
|
|
164
|
+
offspring.inject([]){|memo,child| memo |= child.offspring}
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def uncles_and_aunts
|
|
168
|
+
parents.compact.inject([]){|memo,parent| memo |= parent.siblings}
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def nieces_and_nephews
|
|
172
|
+
siblings.inject([]){|memo,sib| memo |= sib.offspring}
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def family(options = {})
|
|
176
|
+
res = [self] | siblings | parents | offspring
|
|
177
|
+
res |= case options[:half]
|
|
178
|
+
when nil
|
|
179
|
+
[]
|
|
180
|
+
when :include
|
|
181
|
+
half_siblings
|
|
182
|
+
when :father
|
|
183
|
+
paternal_half_siblings
|
|
184
|
+
when :mother
|
|
185
|
+
maternal_half_siblings
|
|
186
|
+
else
|
|
187
|
+
raise WrongOptionValueException, "Admitted values for :half options are: :father, :mother, :include, nil"
|
|
188
|
+
end
|
|
189
|
+
offspring.inject(res){|memo,child| memo |= child.parents}.compact
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def family_hash(options = {})
|
|
193
|
+
roles = [:father, :mother, :children, :siblings]
|
|
194
|
+
roles += case options[:half]
|
|
195
|
+
when nil
|
|
196
|
+
[]
|
|
197
|
+
when :include
|
|
198
|
+
[:half_siblings]
|
|
199
|
+
when :father
|
|
200
|
+
[:paternal_half_siblings]
|
|
201
|
+
when :mother
|
|
202
|
+
[:maternal_half_siblings]
|
|
203
|
+
else
|
|
204
|
+
raise WrongOptionValueException, "Admitted values for :half options are: :father, :mother, :include, nil"
|
|
205
|
+
end
|
|
206
|
+
h = {}
|
|
207
|
+
roles.each{|role| h[role] = self.send(role)}
|
|
208
|
+
h
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def extended_family(options = {})
|
|
212
|
+
(family(options) + grandparents + grandchildren + uncles_and_aunts + nieces_and_nephews).compact
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def extended_family_hash(options = {})
|
|
216
|
+
h = family_hash(options)
|
|
217
|
+
[:paternal_grandfather, :paternal_grandmother, :maternal_grandfather, :maternal_grandmother, :grandchildren, :uncles_and_aunts, :nieces_and_nephews].each{|role| h[role] = self.send(role)}
|
|
218
|
+
h
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def sex_to_s
|
|
222
|
+
case sex
|
|
223
|
+
when sex_male_value
|
|
224
|
+
'male'
|
|
225
|
+
when sex_female_value
|
|
226
|
+
'female'
|
|
227
|
+
else
|
|
228
|
+
raise "undefined sex for #{self}"
|
|
229
|
+
end
|
|
230
|
+
end
|
|
108
231
|
|
|
109
232
|
def is_female?
|
|
110
233
|
sex == sex_female_value
|
|
@@ -115,6 +238,12 @@ module Genealogy
|
|
|
115
238
|
end
|
|
116
239
|
|
|
117
240
|
module ClassMethods
|
|
241
|
+
def males
|
|
242
|
+
where(sex_column => sex_male_value)
|
|
243
|
+
end
|
|
244
|
+
def females
|
|
245
|
+
where(sex_column => sex_female_value)
|
|
246
|
+
end
|
|
118
247
|
end
|
|
119
248
|
|
|
120
249
|
end
|
|
@@ -3,11 +3,11 @@ module Genealogy
|
|
|
3
3
|
extend ActiveSupport::Concern
|
|
4
4
|
|
|
5
5
|
# add method
|
|
6
|
-
def
|
|
7
|
-
raise IncompatibleObjectException, "Linked objects must be instances of the same class" unless obj.is_a? self.
|
|
8
|
-
raise WrongSexException, "Can't add
|
|
9
|
-
self.
|
|
10
|
-
obj.
|
|
6
|
+
def add_current_spouse(obj)
|
|
7
|
+
raise IncompatibleObjectException, "Linked objects must be instances of the same class" unless obj.is_a? self.genealogy_class
|
|
8
|
+
raise WrongSexException, "Can't add current_spouse with same sex" if self.sex == obj.sex
|
|
9
|
+
self.current_spouse = obj
|
|
10
|
+
obj.current_spouse = self
|
|
11
11
|
transaction do
|
|
12
12
|
obj.save!
|
|
13
13
|
save!
|
|
@@ -15,16 +15,21 @@ module Genealogy
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# remove method
|
|
18
|
-
def
|
|
18
|
+
def remove_current_spouse
|
|
19
19
|
transaction do
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
self.
|
|
23
|
-
|
|
20
|
+
ex_current_spouse = current_spouse
|
|
21
|
+
current_spouse.current_spouse = nil
|
|
22
|
+
self.current_spouse = nil
|
|
23
|
+
ex_current_spouse.save!
|
|
24
24
|
save!
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
# query methods
|
|
29
|
+
def eligible_current_spouses
|
|
30
|
+
self.genealogy_class.send("#{Genealogy::OPPOSITESEX[sex_to_s.to_sym]}s") - spouses
|
|
31
|
+
end
|
|
32
|
+
|
|
28
33
|
module ClassMethods
|
|
29
34
|
end
|
|
30
35
|
|
data/lib/genealogy/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: genealogy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- masciugo
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2013-
|
|
11
|
+
date: 2013-07-02 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -94,6 +94,20 @@ dependencies:
|
|
|
94
94
|
- - ! '>='
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
96
|
version: '0'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: gem-release
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ! '>='
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '0'
|
|
104
|
+
type: :development
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ! '>='
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '0'
|
|
97
111
|
description: Genealogy is a ruby gem library which extend ActiveRecord::Base class
|
|
98
112
|
with familiar relationships capabilities in order to build and query genealogies
|
|
99
113
|
email:
|
|
@@ -110,7 +124,7 @@ files:
|
|
|
110
124
|
- lib/genealogy/query_methods.rb
|
|
111
125
|
- lib/genealogy/spouse_methods.rb
|
|
112
126
|
- lib/genealogy/version.rb
|
|
113
|
-
homepage: https://github.com
|
|
127
|
+
homepage: https://github.com/masciugo/genealogy
|
|
114
128
|
licenses:
|
|
115
129
|
- MIT
|
|
116
130
|
metadata: {}
|