genealogy 1.5.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,180 @@
1
+ module Genealogy
2
+ # Module UtilMethods provides methods to run utility methods. It's included by the genealogy enabled AR model
3
+ module UtilMethods
4
+ extend ActiveSupport::Concern
5
+
6
+ include Constants
7
+
8
+ # Genealogy thinks time in term of Date, not DateTime
9
+ # @return [Date]
10
+ def birth
11
+ birth_date.try(:to_date)
12
+ end
13
+
14
+ # Genealogy thinks time in term of Date, not DateTime
15
+ # @return [Date]
16
+ def death
17
+ death_date.try(:to_date)
18
+ end
19
+
20
+ # optimistic (longest) estimation of life period. Calculation is based on available dates and max life expectancy
21
+ # @return [Range] life period or nil if cannot be computable
22
+ def life_range
23
+ if birth
24
+ if death
25
+ birth..death # exact
26
+ else
27
+ birth..(birth + max_le) # estimation based on birth
28
+ end
29
+ elsif death
30
+ (death - max_le)..death # estimation based on death
31
+ end
32
+ end
33
+
34
+ # optimistic (longest) estimation of birth date. Calculation is based on available dates and max life expectancy
35
+ # @return [Range] longest possible birth date interval or nil if cannot be computable
36
+ def birth_range
37
+ if birth
38
+ birth..birth # exact
39
+ elsif death
40
+ (death - max_le)..death # estimation based on death
41
+ end
42
+ end
43
+
44
+ # optimistic (longest) estimation of fertility period. Calculation is based on available dates, max life expectancy and min and max fertility procreation ages
45
+ # @return [Range] fertility period, nil if cannot be computable, false if died before reaching min fertility age
46
+ def fertility_range
47
+ if birth
48
+ if death
49
+ if death > birth + min_fpa
50
+ (birth + min_fpa)..([(birth + max_fpa), death].min) # best estimation
51
+ else
52
+ false # died before reaching min fertility age
53
+ end
54
+ else
55
+ (birth + min_fpa)..(birth + max_fpa) # estimation based on birth
56
+ end
57
+ elsif death
58
+ (death - max_le + min_fpa)..death # estimation based on death
59
+ end
60
+ end
61
+
62
+ # It tests whether fertility range covers specified date
63
+ # @param [Date] date
64
+ # @return [Boolean] or nil if cannot be computable (#fertility_range returns nil)
65
+ def can_procreate_on?(date)
66
+ fertility_range.cover? date if date and fertility_range
67
+ end
68
+
69
+ # It tests whether fertility range overlaps specified period
70
+ # @param [Range] period
71
+ # @return [Boolean] or nil if cannot be computable (#fertility_range returns nil)
72
+ def can_procreate_during?(period)
73
+ fertility_range.overlaps? period if period and fertility_range
74
+ end
75
+
76
+ # @!macro [attach] generate
77
+ # @method $1_birth_range
78
+ # optimistic (longest) estimation of $1's birth date. Calculation is based on receiver's birth or #life_range, max life expectancy and min and max fertility procreation ages
79
+ # @return [Range] longest possible $1's birth date interval or nil when is not computable that is when birth or life range are not available
80
+ def self.generate_method_parent_birth_range(parent)
81
+ define_method "#{parent}_birth_range" do
82
+ if birth
83
+ (birth - gclass.send("max_#{PARENT2SEX[parent]}_procreation_age").years)..(birth - gclass.send("min_#{PARENT2SEX[parent]}_procreation_age").years)
84
+ elsif life_range
85
+ (life_range.begin - gclass.send("max_#{PARENT2SEX[parent]}_procreation_age").years)..(life_range.end - gclass.send("min_#{PARENT2SEX[parent]}_procreation_age").years)
86
+ end
87
+ end
88
+ end
89
+ generate_method_parent_birth_range(:father)
90
+ generate_method_parent_birth_range(:mother)
91
+
92
+ # @!macro [attach] generate
93
+ # @method $1_fertility_range
94
+ # optimistic (longest) estimation of $1's fertility range. Calculation is based on receiver's #$1_birth_range, min and max fertility procreation ages
95
+ # @return [Range] longest possible $1's fertility period or nil when is not computable that is when $1_birth_range is not computable
96
+ def self.generate_method_parent_fertility_range(parent)
97
+ define_method "#{parent}_fertility_range" do
98
+ if parent_birth_range = send("#{parent}_birth_range")
99
+ (parent_birth_range.begin + gclass.send("min_#{PARENT2SEX[parent]}_procreation_age").years)..(parent_birth_range.end + gclass.send("max_#{PARENT2SEX[parent]}_procreation_age").years)
100
+ end
101
+ end
102
+ end
103
+ generate_method_parent_fertility_range(:father)
104
+ generate_method_parent_fertility_range(:mother)
105
+
106
+ # sex in terms of :male or :female
107
+ # @return [Symbol]
108
+ def ssex
109
+ case sex
110
+ when gclass.sex_male_value
111
+ :male
112
+ when gclass.sex_female_value
113
+ :female
114
+ else
115
+ raise SexError, "Sex value not valid for #{self}"
116
+ end
117
+ end
118
+
119
+ # opposite sex in terms of :male or :female
120
+ # @return [Symbol]
121
+ def opposite_ssex
122
+ OPPOSITESEX[ssex]
123
+ end
124
+
125
+ # @return [Boolean]
126
+ def is_female?
127
+ return female? if respond_to?(:female?)
128
+ sex == gclass.sex_female_value
129
+ end
130
+
131
+ # @return [Boolean]
132
+ def is_male?
133
+ return male? if respond_to?(:male?)
134
+ sex == gclass.sex_male_value
135
+ end
136
+
137
+ # max life expectancy in terms of years. It depends on sex
138
+ # @return [Integer]
139
+ def max_le
140
+ gclass.send("max_#{ssex}_life_expectancy").years
141
+ end
142
+
143
+ # max fertility procreation age in terms of years. It depends on sex
144
+ # @return [Integer]
145
+ def max_fpa
146
+ gclass.send("max_#{ssex}_procreation_age").years
147
+ end
148
+
149
+ # min fertility procreation age in terms of years. It depends on sex
150
+ # @return [Integer]
151
+ def min_fpa
152
+ gclass.send("min_#{ssex}_procreation_age").years
153
+ end
154
+
155
+ private
156
+
157
+ def check_incompatible_relationship(*args)
158
+ relationship = args.shift
159
+ args.each do |relative|
160
+ # puts "[#{__method__}]: #{arg} class: #{arg.class}, #{self} class: #{self.class}"
161
+ next if relative.nil?
162
+ check_indiv(relative)
163
+ if gclass.ineligibility_level >= PEDIGREE
164
+ if ineligibles = self.send("ineligible_#{relationship.to_s.pluralize}")
165
+ # puts "[#{__method__}]: checking if #{relative} can be #{relationship} of #{self}"
166
+ raise IncompatibleRelationshipException, "#{relative} can't be #{relationship} of #{self}" if ineligibles.include? relative
167
+ else
168
+ raise IncompatibleRelationshipException, "#{self} already has #{relationship}"
169
+ end
170
+ end
171
+ end
172
+ end
173
+
174
+ def check_indiv(arg, arg_sex=nil)
175
+ raise ArgumentError, "Expected #{self.gclass} object. Got #{arg.class}" unless arg.class.equal? self.gclass
176
+ raise SexError, "Expected a #{arg_sex} as argument. Got a #{arg.ssex}" if arg_sex and arg.ssex != arg_sex
177
+ end
178
+
179
+ end
180
+ end
@@ -1,3 +1,3 @@
1
1
  module Genealogy
2
- VERSION = "1.5.0"
2
+ VERSION = "2.0.0"
3
3
  end
metadata CHANGED
@@ -1,115 +1,185 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: genealogy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - masciugo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-29 00:00:00.000000000 Z
11
+ date: 2015-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '0'
26
+ version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '3.2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '3.2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sqlite3
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ! '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ! '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ! '>='
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ~>
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 2.99.0
75
+ version: '3.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ~>
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: 2.99.0
82
+ version: '3.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec-its
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - ! '>='
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: database_cleaner
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
88
102
  - !ruby/object:Gem::Version
89
103
  version: '0'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - ! '>='
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: redcarpet
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: github-markup
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
95
151
  - !ruby/object:Gem::Version
96
152
  version: '0'
97
153
  - !ruby/object:Gem::Dependency
98
154
  name: gem-release
99
155
  requirement: !ruby/object:Gem::Requirement
100
156
  requirements:
101
- - - ! '>='
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: byebug
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
102
172
  - !ruby/object:Gem::Version
103
173
  version: '0'
104
174
  type: :development
105
175
  prerelease: false
106
176
  version_requirements: !ruby/object:Gem::Requirement
107
177
  requirements:
108
- - - ! '>='
178
+ - - ">="
109
179
  - !ruby/object:Gem::Version
110
180
  version: '0'
111
- description: Genealogy is a ruby gem library which extend ActiveRecord::Base class
112
- with familiar relationships capabilities in order to build and query genealogies
181
+ description: Genealogy is a ruby gem library which extends ActiveRecord models in
182
+ order to make its instances act as relatives so that you can build and query genealogies
113
183
  email:
114
184
  - masciugo@gmail.com
115
185
  executables: []
@@ -119,10 +189,12 @@ files:
119
189
  - lib/genealogy.rb
120
190
  - lib/genealogy/alter_methods.rb
121
191
  - lib/genealogy/constants.rb
192
+ - lib/genealogy/current_spouse_methods.rb
122
193
  - lib/genealogy/exceptions.rb
123
194
  - lib/genealogy/genealogy.rb
195
+ - lib/genealogy/ineligible_methods.rb
124
196
  - lib/genealogy/query_methods.rb
125
- - lib/genealogy/spouse_methods.rb
197
+ - lib/genealogy/util_methods.rb
126
198
  - lib/genealogy/version.rb
127
199
  homepage: https://github.com/masciugo/genealogy
128
200
  licenses:
@@ -134,18 +206,19 @@ require_paths:
134
206
  - lib
135
207
  required_ruby_version: !ruby/object:Gem::Requirement
136
208
  requirements:
137
- - - ! '>='
209
+ - - ">="
138
210
  - !ruby/object:Gem::Version
139
211
  version: '0'
140
212
  required_rubygems_version: !ruby/object:Gem::Requirement
141
213
  requirements:
142
- - - ! '>='
214
+ - - ">="
143
215
  - !ruby/object:Gem::Version
144
216
  version: '0'
145
217
  requirements: []
146
- rubyforge_project: ! '[none]'
147
- rubygems_version: 2.1.10
218
+ rubyforge_project: "[none]"
219
+ rubygems_version: 2.2.2
148
220
  signing_key:
149
221
  specification_version: 4
150
- summary: Organise ActiveRecord models into a genealogical tree structure
222
+ summary: Make ActiveRecord model act as a pedigree
151
223
  test_files: []
224
+ has_rdoc:
@@ -1,53 +0,0 @@
1
- module Genealogy
2
- module SpouseMethods
3
- extend ActiveSupport::Concern
4
-
5
- # add method
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
-
10
- if perform_validation
11
- self.current_spouse = obj
12
- obj.current_spouse = self
13
- transaction do
14
- obj.save!
15
- save!
16
- end
17
- else
18
- transaction do
19
- self.update_attribute(:current_spouse,obj)
20
- obj.update_attribute(:current_spouse,self)
21
- end
22
- end
23
-
24
- end
25
-
26
- # remove method
27
- def remove_current_spouse
28
- if perform_validation
29
- ex_current_spouse = current_spouse
30
- current_spouse.current_spouse = nil
31
- self.current_spouse = nil
32
- transaction do
33
- ex_current_spouse.save!
34
- save!
35
- end
36
- else
37
- transaction do
38
- current_spouse.update_attribute(:current_spouse,nil)
39
- self.update_attribute(:current_spouse,nil)
40
- end
41
- end
42
- end
43
-
44
- # query methods
45
- def eligible_current_spouses
46
- self.genealogy_class.send("#{Genealogy::OPPOSITESEX[sex_to_s.to_sym]}s") - spouses
47
- end
48
-
49
- module ClassMethods
50
- end
51
-
52
- end
53
- end