Module: Genealogy::QueryMethods

Extended by:
ActiveSupport::Concern
Includes:
Constants
Defined in:
lib/genealogy/query_methods.rb

Overview

Module QueryMethods provides methods to run genealogy queries to retrive relatives by role. It's included by the genealogy enabled AR model

Defined Under Namespace

Modules: ClassMethods

Constant Summary

Constants included from Constants

Constants::AKA, Constants::DEFAULTS, Constants::LINEAGE2PARENT, Constants::OFF, Constants::OPPOSITESEX, Constants::PARENT2LINEAGE, Constants::PARENT2SEX, Constants::PEDIGREE, Constants::PEDIGREE_AND_DATES, Constants::SEX2PARENT

Instance Method Summary collapse

Instance Method Details

#ancestors(options = {}) ⇒ ActiveRecord::Relation

get list of known ancestrors iterateing over parents

Parameters:

  • options (Hash) (defaults to: {})

Returns:

  • (ActiveRecord::Relation)

    list of ancestors


132
133
134
135
136
137
138
139
140
# File 'lib/genealogy/query_methods.rb', line 132

def ancestors(options = {})
  ids = []
  remaining_ids = parents.compact.map(&:id)
  until remaining_ids.empty?
    ids << remaining_ids.shift
    remaining_ids += gclass.find(ids.last).parents.compact.map(&:id)
  end
  gclass.where(id: ids)
end

#aunts(options = {}) ⇒ Object

See Also:


190
191
192
# File 'lib/genealogy/query_methods.rb', line 190

def aunts(options = {})
  uncles_and_aunts(options).females
end

#children(options = {}) ⇒ ActiveRecord::Relation

Returns children.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • spouse (Object)

    to filter children by spouse

Returns:

  • (ActiveRecord::Relation)

    children

Raises:


52
53
54
55
56
57
58
59
60
# File 'lib/genealogy/query_methods.rb', line 52

def children(options = {})
  raise SexError, "Sex value not valid for #{self}. It's needed to look for children" unless gclass.sex_values.include? sex
  result = gclass.where("#{SEX2PARENT[ssex]}_id" => self)
  if options.keys.include? :spouse
    check_indiv(spouse = options[:spouse],opposite_ssex)
    result = result.where("#{SEX2PARENT[opposite_ssex]}_id" => spouse ) if spouse
  end
  result
end

#cousins(options = {}) ⇒ ActiveRecord::Relation

Returns list of uncles and aunts' children.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • lineage (Symbol)

    to filter uncles by lineage: :paternal or :maternal

  • half (Symbol)

    to filter uncles (see #siblings)

Returns:

  • (ActiveRecord::Relation)

    list of uncles and aunts' children


218
219
220
221
# File 'lib/genealogy/query_methods.rb', line 218

def cousins(options = {})
  ids = uncles_and_aunts(options).inject([]){|memo,uncle| memo |= uncle.children.pluck(:id)}
  gclass.where(id: ids)
end

#descendantsActiveRecord::Relation

get list of known descendants iterateing over children …

Returns:

  • (ActiveRecord::Relation)

    list of descendants


145
146
147
148
149
150
151
152
153
154
# File 'lib/genealogy/query_methods.rb', line 145

def descendants
  ids = []
  remaining_ids = children.map(&:id)
  until remaining_ids.empty?
    ids << remaining_ids.shift
    remaining_ids += gclass.find(ids.last).children.pluck(:id)    # break if (remaining_ids - ids).empty? can be necessary in case of loop. Idem for ancestors method

  end
  gclass.where(id: ids)
end

#extended_family(options = {}) ⇒ Object

family with option extended: :true

See Also:


280
281
282
# File 'lib/genealogy/query_methods.rb', line 280

def extended_family(options = {})
  family(options.merge(extended: true))
end

#extended_family_hash(options = {}) ⇒ Object

family_hash with option extended: :true

See Also:


266
267
268
# File 'lib/genealogy/query_methods.rb', line 266

def extended_family_hash(options = {})
  family_hash(options.merge(extended: true))
end

#family(options = {}) ⇒ Array

family individuals

Returns:

  • (Array)

See Also:


273
274
275
276
# File 'lib/genealogy/query_methods.rb', line 273

def family(options = {})
  hash = family_hash(options)
  hash.keys.inject([]){|tot,k| tot << hash[k] }.compact.flatten
end

#family_hash(options = {}) ⇒ Hash

family hash with roles as keys? :spouse and individuals as values. Defaults roles are :father, :mother, :children, :siblings and current_spouse if enabled

Parameters:

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • half (Symbol)

    to filter siblings (see #siblings)

  • extended (Boolean)

    to include roles for grandparents, grandchildren, uncles, aunts, nieces, nephews and cousins

Returns:

  • (Hash)

    family hash with roles as keys? :spouse and individuals as values.


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
# File 'lib/genealogy/query_methods.rb', line 245

def family_hash(options = {})
  roles = [:father, :mother, :children, :siblings]
  roles += [:current_spouse] if self.class.current_spouse_enabled
  roles += case options[:half]
    when nil
      []
    when :include
      [:half_siblings]
    when :father
      [:paternal_half_siblings]
    when :mother
      [:maternal_half_siblings]
    else
      raise ArgumentError, "Admitted values for :half options are: :father, :mother, :include, nil"
  end
  roles += [:paternal_grandfather, :paternal_grandmother, :maternal_grandfather, :maternal_grandmother, :grandchildren, :uncles_and_aunts, :nieces_and_nephews, :cousins] if options[:extended] == true
  roles.inject({}){|res,role| res.merge!({role => self.send(role)})}
end

#grandchildrenActiveRecord::Relation

Returns list of grandchildren.

Returns:

  • (ActiveRecord::Relation)

    list of grandchildren


157
158
159
# File 'lib/genealogy/query_methods.rb', line 157

def grandchildren
  result = children.inject([]){|memo,child| memo |= child.children}
end

#grandparents4-elements Array

Returns paternal_grandfather, paternal_grandmother, maternal_grandfather, maternal_grandmother.

Returns:

  • (4-elements Array)

    paternal_grandfather, paternal_grandmother, maternal_grandfather, maternal_grandmother


40
41
42
# File 'lib/genealogy/query_methods.rb', line 40

def grandparents
  [paternal_grandfather, paternal_grandmother, maternal_grandfather, maternal_grandmother]
end

#great_grandchildrenActiveRecord::Relation

Returns list of grat-grandchildren.

Returns:

  • (ActiveRecord::Relation)

    list of grat-grandchildren


162
163
164
# File 'lib/genealogy/query_methods.rb', line 162

def great_grandchildren
  result = grandchildren.compact.inject([]){|memo,grandchild| memo |= grandchild.children}
end

#great_grandparents8-elements Array

Returns paternal_grandfather's father, paternal_grandmother's father, maternal_grandfather's father, maternal_grandmother's father, paternal_grandfather's mother, paternal_grandmother's mother, maternal_grandfather's mother, maternal_grandmother's mother.

Returns:

  • (8-elements Array)

    paternal_grandfather's father, paternal_grandmother's father, maternal_grandfather's father, maternal_grandmother's father, paternal_grandfather's mother, paternal_grandmother's mother, maternal_grandfather's mother, maternal_grandmother's mother


45
46
47
# File 'lib/genealogy/query_methods.rb', line 45

def great_grandparents
  grandparents.inject([]){|memo, gp| memo += (gp.try(:parents) || [nil,nil]) }.flatten
end

#half_siblings(options = {}) ⇒ Object

siblings with option half: :only

See Also:


113
114
115
# File 'lib/genealogy/query_methods.rb', line 113

def half_siblings(options = {})
  siblings(options.merge(half: :only))
end

#maternal_aunts(options = {}) ⇒ Object

See Also:


210
211
212
# File 'lib/genealogy/query_methods.rb', line 210

def maternal_aunts(options = {})
  aunts(options.merge(lineage: :maternal))
end

#maternal_grandfatherActiveRecord, NilClass

Returns:

  • (ActiveRecord, NilClass)

21
22
23
# File 'lib/genealogy/query_methods.rb', line 21

def maternal_grandfather
  mother && mother.father
end

#maternal_grandmotherActiveRecord, NilClass

Returns:

  • (ActiveRecord, NilClass)

25
26
27
# File 'lib/genealogy/query_methods.rb', line 25

def maternal_grandmother
  mother && mother.mother
end

#maternal_grandparents2-elements Array

Returns maternal_grandfather and maternal_grandmother.

Returns:

  • (2-elements Array)

    maternal_grandfather and maternal_grandmother


35
36
37
# File 'lib/genealogy/query_methods.rb', line 35

def maternal_grandparents
  (mother && mother.parents) || [nil,nil]
end

#maternal_half_siblings(options = {}) ⇒ Object

siblings with option half: :mother

See Also:


125
126
127
# File 'lib/genealogy/query_methods.rb', line 125

def maternal_half_siblings(options = {})
  siblings(options.merge(half: :mother))
end

#maternal_uncles(options = {}) ⇒ Object

See Also:


200
201
202
# File 'lib/genealogy/query_methods.rb', line 200

def maternal_uncles(options = {})
  uncles(options.merge(lineage: :maternal))
end

#nephews(options = {}) ⇒ Object


232
233
234
# File 'lib/genealogy/query_methods.rb', line 232

def nephews(options = {})
  nieces_and_nephews.males
end

#nieces(options = {}) ⇒ Object


237
238
239
# File 'lib/genealogy/query_methods.rb', line 237

def nieces(options = {})
  nieces_and_nephews.females
end

#nieces_and_nephews(options = {}) ⇒ ActiveRecord::Relation

Returns list of nieces and nephews.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • half (Symbol)

    to filter siblings (see #siblings)

Returns:

  • (ActiveRecord::Relation)

    list of nieces and nephews


226
227
228
229
# File 'lib/genealogy/query_methods.rb', line 226

def nieces_and_nephews(options = {})
  ids = siblings(options).inject([]){|memo,sib| memo |= sib.children.pluck(:id)}
  gclass.where(id: ids)
end

#parents2-elements Array

Returns father and mother.

Returns:

  • (2-elements Array)

    father and mother


9
10
11
# File 'lib/genealogy/query_methods.rb', line 9

def parents
  [father,mother]
end

#paternal_aunts(options = {}) ⇒ Object

See Also:


205
206
207
# File 'lib/genealogy/query_methods.rb', line 205

def paternal_aunts(options = {})
  aunts(options.merge(lineage: :paternal))
end

#paternal_grandfatherActiveRecord, NilClass

Returns:

  • (ActiveRecord, NilClass)

13
14
15
# File 'lib/genealogy/query_methods.rb', line 13

def paternal_grandfather
  father && father.father
end

#paternal_grandmotherActiveRecord, NilClass

Returns:

  • (ActiveRecord, NilClass)

17
18
19
# File 'lib/genealogy/query_methods.rb', line 17

def paternal_grandmother
  father && father.mother
end

#paternal_grandparents2-elements Array

Returns paternal_grandfather and paternal_grandmother.

Returns:

  • (2-elements Array)

    paternal_grandfather and paternal_grandmother


30
31
32
# File 'lib/genealogy/query_methods.rb', line 30

def paternal_grandparents
  (father && father.parents) || [nil,nil]
end

#paternal_half_siblings(options = {}) ⇒ Object

siblings with option half: :father

See Also:


119
120
121
# File 'lib/genealogy/query_methods.rb', line 119

def paternal_half_siblings(options = {})
  siblings(options.merge(half: :father))
end

#paternal_uncles(options = {}) ⇒ Object

See Also:


195
196
197
# File 'lib/genealogy/query_methods.rb', line 195

def paternal_uncles(options = {})
  uncles(options.merge(lineage: :paternal))
end

#siblings(options = {}) ⇒ ActiveRecord::Relation

Returns list of fullsiblings and/or halfsiblings.

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • half (Symbol)

    let you filter siblings. Possible values are: :father for paternal halfsiblings :mother for maternal halfsiblings :only for all halfsiblings :include for fullsiblings and halfsiblings

Returns:

  • (ActiveRecord::Relation)

    list of fullsiblings and/or halfsiblings


74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/genealogy/query_methods.rb', line 74

def siblings(options = {})
  spouse = options[:spouse]
  result = gclass.where("id != ?",id)
  case options[:half]
  when nil # only full siblings
    result.all_with(:parents).where(father_id: father, mother_id: mother)
  when :father # common father
    result = result.all_with(:father).where(father_id: father)
    if spouse 
      check_indiv(spouse, :female)
      result.where(mother_id: spouse)
    elsif mother
      result.where("mother_id != ? or mother_id is ?", mother_id, nil)
    else
      result
    end
  when :mother # common mother
    result = result.all_with(:mother).where(mother_id: mother)
    if spouse
      check_indiv(spouse, :male)
      result.where(father_id: spouse)
    elsif father
      result.where("father_id != ? or father_id is ?", father_id, nil)
    else
      result
    end
  when :only # only half siblings
    ids = siblings(half: :father).pluck(:id) | siblings(half: :mother).pluck(:id)
    result.where(id: ids)
  when :include # including half siblings
    result.where("father_id == ? or mother_id == ?", father_id, mother_id)
  else
    raise ArgumentError, "Admitted values for :half options are: :father, :mother, false, true or nil"
  end

end

#spousesActiveRecord::Relation

Returns list of individuals with whom has had children.

Returns:

  • (ActiveRecord::Relation)

    list of individuals with whom has had children


63
64
65
# File 'lib/genealogy/query_methods.rb', line 63

def spouses
  gclass.where(id: children.pluck("#{SEX2PARENT[opposite_ssex]}_id".to_sym).compact.uniq)
end

#uncles(options = {}) ⇒ Object

See Also:


185
186
187
# File 'lib/genealogy/query_methods.rb', line 185

def uncles(options = {})
  uncles_and_aunts(options).males
end

#uncles_and_aunts(options = {}) ⇒ ActiveRecord::Relation

list of uncles and aunts iterating through parents' siblings

Parameters:

  • options (Hash) (defaults to: {})

Options Hash (options):

  • lineage (Symbol)

    to filter by lineage: :paternal or :maternal

  • half (Symbol)

    to filter by half siblings (see #siblings)

Returns:

  • (ActiveRecord::Relation)

    list of uncles and aunts


171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/genealogy/query_methods.rb', line 171

def uncles_and_aunts(options={})
  relation = case options[:lineage]
  when :paternal
    [father]
  when :maternal
    [mother]
  else
    parents
  end
  ids = relation.compact.inject([]){|memo,parent| memo |= parent.siblings(half: options[:half]).pluck(:id)}
  gclass.where(id: ids)
end