eco-helpers 2.0.12 → 2.0.17
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 +4 -4
- data/CHANGELOG.md +80 -73
- data/eco-helpers.gemspec +6 -4
- data/lib/eco-helpers.rb +1 -0
- data/lib/eco/api/common/base_loader.rb +14 -0
- data/lib/eco/api/common/loaders/use_case.rb +1 -1
- data/lib/eco/api/common/people/default_parsers/date_parser.rb +11 -1
- data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +1 -1
- data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +11 -11
- data/lib/eco/api/common/people/person_entry.rb +9 -2
- data/lib/eco/api/common/people/supervisor_helpers.rb +27 -0
- data/lib/eco/api/common/session/file_manager.rb +2 -2
- data/lib/eco/api/common/session/mailer.rb +0 -1
- data/lib/eco/api/common/session/s3_uploader.rb +0 -1
- data/lib/eco/api/common/session/sftp.rb +0 -1
- data/lib/eco/api/error.rb +5 -3
- data/lib/eco/api/microcases.rb +3 -1
- data/lib/eco/api/microcases/append_usergroups.rb +0 -1
- data/lib/eco/api/microcases/people_cache.rb +2 -2
- data/lib/eco/api/microcases/people_load.rb +2 -2
- data/lib/eco/api/microcases/people_refresh.rb +2 -2
- data/lib/eco/api/microcases/people_search.rb +6 -6
- data/lib/eco/api/microcases/preserve_default_tag.rb +23 -0
- data/lib/eco/api/microcases/preserve_filter_tags.rb +28 -0
- data/lib/eco/api/microcases/preserve_policy_groups.rb +30 -0
- data/lib/eco/api/microcases/set_account.rb +0 -1
- data/lib/eco/api/organization.rb +1 -0
- data/lib/eco/api/organization/people.rb +7 -0
- data/lib/eco/api/organization/people_analytics.rb +60 -0
- data/lib/eco/api/organization/presets_factory.rb +116 -93
- data/lib/eco/api/organization/presets_integrity.json +58 -0
- data/lib/eco/api/organization/presets_values.json +5 -4
- data/lib/eco/api/policies/default_policies/99_user_access_policy.rb +0 -30
- data/lib/eco/api/session.rb +1 -20
- data/lib/eco/api/session/batch.rb +42 -10
- data/lib/eco/api/session/batch/job.rb +3 -0
- data/lib/eco/api/session/config.rb +16 -15
- data/lib/eco/api/session/config/api.rb +4 -0
- data/lib/eco/api/session/config/apis.rb +14 -0
- data/lib/eco/api/session/config/files.rb +7 -0
- data/lib/eco/api/session/config/people.rb +3 -19
- data/lib/eco/api/usecases.rb +2 -0
- data/lib/eco/api/usecases/default_cases.rb +4 -1
- data/lib/eco/api/usecases/default_cases/abstract_policygroup_abilities_case.rb +161 -0
- data/lib/eco/api/usecases/default_cases/analyse_people_case.rb +76 -0
- data/lib/eco/api/usecases/default_cases/codes_to_tags_case.rb +2 -3
- data/lib/eco/api/usecases/default_cases/hris_case.rb +14 -8
- data/lib/eco/api/usecases/default_cases/reset_landing_page_case.rb +11 -1
- data/lib/eco/api/usecases/default_cases/restore_db_case.rb +1 -2
- data/lib/eco/api/usecases/default_cases/supers_cyclic_identify_case.rb +72 -0
- data/lib/eco/api/usecases/default_cases/supers_hierarchy_case.rb +59 -0
- data/lib/eco/api/usecases/default_cases/to_csv_case.rb +104 -26
- data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +62 -36
- data/lib/eco/cli.rb +0 -10
- data/lib/eco/cli/config/default/options.rb +19 -17
- data/lib/eco/cli/config/default/people_filters.rb +3 -3
- data/lib/eco/cli/config/default/usecases.rb +77 -25
- data/lib/eco/cli/config/default/workflow.rb +6 -1
- data/lib/eco/cli/config/help.rb +1 -0
- data/lib/eco/cli/config/options_set.rb +106 -13
- data/lib/eco/cli/config/use_cases.rb +33 -33
- data/lib/eco/cli/scripting/args_helpers.rb +30 -3
- data/lib/eco/data.rb +1 -0
- data/lib/eco/data/crypto/encryption.rb +3 -3
- data/lib/eco/data/files/directory.rb +28 -20
- data/lib/eco/data/files/helpers.rb +6 -4
- data/lib/eco/data/fuzzy_match.rb +119 -0
- data/lib/eco/data/fuzzy_match/array_helpers.rb +75 -0
- data/lib/eco/data/fuzzy_match/chars_position_score.rb +37 -0
- data/lib/eco/data/fuzzy_match/ngrams_score.rb +73 -0
- data/lib/eco/data/fuzzy_match/pairing.rb +102 -0
- data/lib/eco/data/fuzzy_match/result.rb +67 -0
- data/lib/eco/data/fuzzy_match/results.rb +53 -0
- data/lib/eco/data/fuzzy_match/score.rb +44 -0
- data/lib/eco/data/fuzzy_match/stop_words.rb +35 -0
- data/lib/eco/data/fuzzy_match/string_helpers.rb +69 -0
- data/lib/eco/version.rb +1 -1
- metadata +86 -10
- data/lib/eco/api/microcases/refresh_abilities.rb +0 -19
- data/lib/eco/api/organization/presets_reference.json +0 -59
- data/lib/eco/api/usecases/default_cases/refresh_abilities_case.rb +0 -30
@@ -1,31 +1,31 @@
|
|
1
1
|
class Eco::API::Common::People::DefaultParsers::PolicyGroupsParser < Eco::API::Common::Loaders::Parser
|
2
2
|
attribute "policy_group_ids"
|
3
|
+
parsing_phase :final
|
3
4
|
|
4
5
|
def parser(hash, deps)
|
5
|
-
policy_group_ids = []
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
policy_group_ids = hash["policy_group_ids"] || []
|
7
|
+
policy_group_ids.map do |name|
|
8
|
+
policy_groups.to_id(name&.downcase.strip)
|
9
|
+
end.compact.tap do |pg_names|
|
10
|
+
pg_names.push(default_id) if pg_names.empty?
|
10
11
|
end
|
11
|
-
policy_group_ids.empty?? default_id : policy_group_ids.join("|")
|
12
12
|
end
|
13
13
|
|
14
14
|
def serializer(person, deps)
|
15
15
|
ids = person&.account&.policy_group_ids || []
|
16
16
|
ids.map do |id|
|
17
17
|
policy_groups.to_name(id)
|
18
|
-
end.compact
|
18
|
+
end.compact
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
22
22
|
|
23
|
-
def
|
24
|
-
@
|
23
|
+
def default_id
|
24
|
+
@default_id ||= policy_groups.to_id(config.people.default_usergroup)
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
@
|
27
|
+
def policy_groups
|
28
|
+
@policy_groups ||= config.policy_groups
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
@@ -57,6 +57,11 @@ module Eco
|
|
57
57
|
@internal_entry
|
58
58
|
end
|
59
59
|
|
60
|
+
# @return [Hash] entry `Hash` with **internal** attribute names, but **external** types and values.
|
61
|
+
def mapped_entry
|
62
|
+
@mapped_entry
|
63
|
+
end
|
64
|
+
|
60
65
|
# @note values ready to be set to a person.
|
61
66
|
# @return [Hash] entry `Hash` with **internal** attribute names, values and types.
|
62
67
|
def final_entry
|
@@ -205,7 +210,6 @@ module Eco
|
|
205
210
|
# @param exclude [String, Array<String>] account properties that should not be set/changed to the person.
|
206
211
|
def set_account(person, exclude: nil)
|
207
212
|
person.account = {} if !person.account
|
208
|
-
person.account.permissions_preset = nil unless person.account.permissions_preset = "custom"
|
209
213
|
scoped_attrs = @emap.account_attrs - into_a(exclude)
|
210
214
|
@final_entry.slice(*scoped_attrs).each do |attr, value|
|
211
215
|
set_part(person.account, attr, value)
|
@@ -285,7 +289,10 @@ module Eco
|
|
285
289
|
# @param internal_entry [Hash] entry with **internal** names and values, but **external** types.
|
286
290
|
# @return [Hash] entry with **internal** names and **external** values and types.
|
287
291
|
def _mapped_serializing(internal_entry)
|
288
|
-
internal_entry.merge(_serialize_values(internal_entry, :internal))
|
292
|
+
mapped_hash = internal_entry.merge(_serialize_values(internal_entry, :internal))
|
293
|
+
model_attrs = @person_parser.all_model_attrs - ["send_invites"]
|
294
|
+
aux_hash = mapped_hash.slice(*model_attrs)
|
295
|
+
merge_missing_attrs(aux_hash, mapped_hash)
|
289
296
|
end
|
290
297
|
|
291
298
|
# Parsing helper that just **parses the values** that have a parser/serializer defined.
|
@@ -15,6 +15,7 @@ module Eco
|
|
15
15
|
# Reorders as follows:
|
16
16
|
# 1. supervisors, people with no supervisor or where their supervisor not present
|
17
17
|
# 2. subordinates
|
18
|
+
# @return [Array<Entry>] `values` sorted by supervisors/subordinates
|
18
19
|
def sort_by_supervisors(values, supervisors_first: true)
|
19
20
|
raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
|
20
21
|
return [] unless values && values.is_a?(Enumerable)
|
@@ -32,6 +33,32 @@ module Eco
|
|
32
33
|
roam.call(supervisors_tree(values))
|
33
34
|
end
|
34
35
|
|
36
|
+
# Identifies all the cyclic supervisor chains
|
37
|
+
# @note as `supervisors_tree` will have any entry involved in a cycle at the top, it just checks all the top entries against their offspring
|
38
|
+
# @return [Array<Array>] the sets of entries that are cyclic
|
39
|
+
def identify_cyclic_chains(values)
|
40
|
+
raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
|
41
|
+
return [] unless values && values.is_a?(Enumerable)
|
42
|
+
|
43
|
+
identify = Proc.new do |top_sup, offspring, chain = [top_sup]|
|
44
|
+
next [] if offspring.empty?
|
45
|
+
offspring.each_with_object([]) do |(sup, subordinates), set|
|
46
|
+
break set unless set.empty?
|
47
|
+
if top_sup.supervisor_id == sup.id
|
48
|
+
set.concat(chain, [sup])
|
49
|
+
else
|
50
|
+
set = identify.call(top_sup, subordinates, chain | [sup])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
supervisors_tree(values).each_with_object([]) do |(top_sup, offspring), sets|
|
56
|
+
if (set = identify.call(top_sup, offspring)) && !set.empty?
|
57
|
+
sets.push(set)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
35
62
|
def tree_to_str(tree, lev: 0)
|
36
63
|
raise "Required Hash tree structure. Given: #{tree.class}" unless tree.is_a?(Hash)
|
37
64
|
"".tap do |str|
|
@@ -20,8 +20,8 @@ module Eco
|
|
20
20
|
begin
|
21
21
|
@dir = Eco::Data::Files::Directory.new(value)
|
22
22
|
@dir_path = @dir.create
|
23
|
-
rescue
|
24
|
-
logger.error("could not create or make any sense of directory '#{value}'")
|
23
|
+
rescue Exception => e
|
24
|
+
logger.error("could not create or make any sense of directory '#{value}': #{e.to_s}")
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
data/lib/eco/api/error.rb
CHANGED
@@ -80,6 +80,7 @@ module Eco
|
|
80
80
|
next 1 if k1 < k2
|
81
81
|
0
|
82
82
|
end.tap do |siblings|
|
83
|
+
siblings.delete(Unclassified)
|
83
84
|
if direct
|
84
85
|
siblings.reject! do |si|
|
85
86
|
siblings.any? {|s| si < s}
|
@@ -96,17 +97,18 @@ module Eco
|
|
96
97
|
err_msg =~ @match
|
97
98
|
end
|
98
99
|
|
99
|
-
def get_type(err_msg)
|
100
|
+
def get_type(err_msg, first: true)
|
100
101
|
type = nil
|
101
102
|
descendants(direct: true).reverse.each do |klass|
|
102
103
|
if klass.err_match?(err_msg)
|
103
104
|
type = klass
|
104
105
|
if klass.descendants?(direct: true)
|
105
|
-
type = klass.get_type(err_msg) || type
|
106
|
+
type = klass.get_type(err_msg, first: false) || type
|
106
107
|
end
|
107
108
|
end
|
108
109
|
end
|
109
|
-
type
|
110
|
+
return type unless first
|
111
|
+
type || Unclassified
|
110
112
|
end
|
111
113
|
|
112
114
|
def known_err_class?(klass)
|
data/lib/eco/api/microcases.rb
CHANGED
@@ -19,7 +19,9 @@ require_relative 'microcases/people_cache'
|
|
19
19
|
require_relative 'microcases/people_load'
|
20
20
|
require_relative 'microcases/people_refresh'
|
21
21
|
require_relative 'microcases/people_search'
|
22
|
-
require_relative 'microcases/
|
22
|
+
require_relative 'microcases/preserve_filter_tags'
|
23
|
+
require_relative 'microcases/preserve_default_tag'
|
24
|
+
require_relative 'microcases/preserve_policy_groups'
|
23
25
|
require_relative 'microcases/set_account'
|
24
26
|
require_relative 'microcases/set_core_with_supervisor'
|
25
27
|
require_relative 'microcases/set_core'
|
@@ -9,9 +9,9 @@ module Eco
|
|
9
9
|
|
10
10
|
start = Time.now
|
11
11
|
people = session.batch.get_people
|
12
|
-
secs = Time.now - start
|
12
|
+
secs = (Time.now - start).round(3)
|
13
13
|
cnt = people.count
|
14
|
-
per_sec = (cnt.to_f / secs).
|
14
|
+
per_sec = (cnt.to_f / secs).round(2)
|
15
15
|
logger.info("Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)")
|
16
16
|
|
17
17
|
file = file_manager.save_json(people, filename, :timestamp)
|
@@ -34,9 +34,9 @@ module Eco
|
|
34
34
|
|
35
35
|
start = Time.now
|
36
36
|
session.batch.get_people.tap do |people|
|
37
|
-
secs = Time.now - start
|
37
|
+
secs = (Time.now - start).round(3)
|
38
38
|
cnt = people.count
|
39
|
-
per_sec = (cnt.to_f / secs).
|
39
|
+
per_sec = (cnt.to_f / secs).round(2)
|
40
40
|
logger.info("Loaded #{cnt} people in #{secs} seconds (#{per_sec} people/sec)")
|
41
41
|
|
42
42
|
if modifier.include?(:save) && people && people.length > 0
|
@@ -21,9 +21,9 @@ module Eco
|
|
21
21
|
|
22
22
|
start = Time.now
|
23
23
|
entries = session.batch.get_people(people, silent: true)
|
24
|
-
secs = Time.now - start
|
24
|
+
secs = (Time.now - start).round(3)
|
25
25
|
cnt = entries.count
|
26
|
-
per_sec = (cnt.to_f / secs).
|
26
|
+
per_sec = (cnt.to_f / secs).round(2)
|
27
27
|
logger.info("Re-loaded #{cnt} people (out of #{people.length}) in #{secs} seconds (#{per_sec} people/sec)")
|
28
28
|
|
29
29
|
missing = people.length - entries.length
|
@@ -14,10 +14,10 @@ module Eco
|
|
14
14
|
|
15
15
|
start = Time.now
|
16
16
|
people = session.batch.search(data, silent: silent).yield_self do |status|
|
17
|
-
secs = Time.now - start
|
17
|
+
secs = (Time.now - start).round(3)
|
18
18
|
Eco::API::Organization::People.new(status.people).tap do |people|
|
19
19
|
cnt = people.count
|
20
|
-
per_sec = (cnt.to_f / secs).
|
20
|
+
per_sec = (cnt.to_f / secs).round(2)
|
21
21
|
msg = "... could get #{cnt} people (out of #{data.length} entries) in #{secs} seconds (#{per_sec} people/sec)"
|
22
22
|
session.logger.info(msg)
|
23
23
|
end
|
@@ -29,10 +29,10 @@ module Eco
|
|
29
29
|
session.logger.info(" Going to api get #{supers.length} current supervisors...")
|
30
30
|
start = Time.now
|
31
31
|
people = session.batch.search(supers, silent: silent).yield_self do |status|
|
32
|
-
secs = Time.now - start
|
32
|
+
secs = (Time.now - start).round(3)
|
33
33
|
found = status.people
|
34
34
|
cnt = found.count
|
35
|
-
per_sec = (cnt.to_f / secs).
|
35
|
+
per_sec = (cnt.to_f / secs).round(2)
|
36
36
|
msg = "... could find #{cnt} current supers (out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
|
37
37
|
session.logger.info(msg)
|
38
38
|
people.merge(found, strict: micro.strict_search?(options))
|
@@ -46,10 +46,10 @@ module Eco
|
|
46
46
|
start = Time.now
|
47
47
|
|
48
48
|
people = session.batch.search(supers, silent: silent).yield_self do |status|
|
49
|
-
secs = Time.now - start
|
49
|
+
secs = (Time.now - start).round(3)
|
50
50
|
found = status.people
|
51
51
|
cnt = found.count
|
52
|
-
per_sec = (cnt.to_f / secs).
|
52
|
+
per_sec = (cnt.to_f / secs).round(2)
|
53
53
|
msg = "... could find #{cnt} input supers (out of #{supers.length}) in #{secs} seconds (#{per_sec} people/sec)"
|
54
54
|
session.logger.info(msg)
|
55
55
|
people.merge(found, strict: micro.strict_search?(options))
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
class MicroCases
|
4
|
+
# Helper to preserve the original `default_tag`.
|
5
|
+
# @note
|
6
|
+
# 1. It only works if the original value of `default_tag` was **not** empty
|
7
|
+
# @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
|
8
|
+
# @param options [Hash] the options.
|
9
|
+
# @return [String] the final value of `default_tag`.
|
10
|
+
def preserve_default_tag(person, options)
|
11
|
+
if account = person.account
|
12
|
+
if account.as_update.key?("default_tag")
|
13
|
+
if original = person.original_doc.dig("account", "default_tag")
|
14
|
+
person.account.default_tag = original
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
person.account&.default_tag
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
class MicroCases
|
4
|
+
# Helper to preserve the original filter tags.
|
5
|
+
# @note
|
6
|
+
# 1. It only works if the original value of `filter_tags` was **not** empty
|
7
|
+
# @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
|
8
|
+
# @param options [Hash] the options.
|
9
|
+
# @param keep_new [Boolean] tells if it should keep the new tags or get rid of them.
|
10
|
+
# @return [Array<String>] the final value of `filter_tags`.
|
11
|
+
def preserve_filter_tags(person, options, keep_new: false)
|
12
|
+
if person.as_update.key?("filter_tags")
|
13
|
+
if original = person.original_doc["filter_tags"]
|
14
|
+
unless original.empty?
|
15
|
+
if keep_new
|
16
|
+
person.filter_tags += original
|
17
|
+
else
|
18
|
+
person.filter_tags = original
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
person.filter_tags
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
class MicroCases
|
4
|
+
# Helper to preserve the original `policy_group_ids`.
|
5
|
+
# @note
|
6
|
+
# 1. It only works if the original value of `policy_group_ids` was **not** empty
|
7
|
+
# @param person [Ecoportal::API::V1::Person] the person we want to update, carrying the changes to be done.
|
8
|
+
# @param options [Hash] the options.
|
9
|
+
# @param keep_new [Boolean] tells if it should keep the new policy groups or get rid of them.
|
10
|
+
# @return [String] the final value of `policy_group_ids`.
|
11
|
+
def preserve_policy_groups(person, options, keep_new: false)
|
12
|
+
if account = person.account
|
13
|
+
if account.as_update.key?("policy_group_ids")
|
14
|
+
if original = person.original_doc.dig("account", "policy_group_ids")
|
15
|
+
unless original.empty?
|
16
|
+
if keep_new
|
17
|
+
person.account.policy_group_ids += original
|
18
|
+
else
|
19
|
+
person.account.policy_group_ids = original
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
person.account&.policy_group_ids
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -11,7 +11,6 @@ module Eco
|
|
11
11
|
person.account.send_invites = options[:send_invites] if options.key?(:send_invites)
|
12
12
|
micro.refresh_default_tag(entry, person, options)
|
13
13
|
micro.fix_default_group(entry, person, options)
|
14
|
-
micro.refresh_abilities(person, options)
|
15
14
|
end
|
16
15
|
end
|
17
16
|
|
data/lib/eco/api/organization.rb
CHANGED
@@ -9,6 +9,7 @@ require_relative 'organization/tag_tree'
|
|
9
9
|
require_relative 'organization/presets_factory'
|
10
10
|
require_relative 'organization/preferences'
|
11
11
|
require_relative 'organization/people'
|
12
|
+
require_relative 'organization/people_analytics'
|
12
13
|
require_relative 'organization/person_schemas'
|
13
14
|
require_relative 'organization/policy_groups'
|
14
15
|
require_relative 'organization/login_providers'
|
@@ -176,6 +176,12 @@ module Eco
|
|
176
176
|
end
|
177
177
|
# @!endgroup
|
178
178
|
|
179
|
+
# @!group Helper methods
|
180
|
+
def analytics
|
181
|
+
Eco::API::Organization::PeopleAnalytics.new(self.to_a)
|
182
|
+
end
|
183
|
+
# @!endgroup
|
184
|
+
|
179
185
|
protected
|
180
186
|
|
181
187
|
def on_change
|
@@ -190,6 +196,7 @@ module Eco
|
|
190
196
|
@by_external_id = to_h('external_id')
|
191
197
|
@by_users_email = users.to_h('email')
|
192
198
|
@by_non_users_email = non_users.to_h('email')
|
199
|
+
@by_email = to_h('email')
|
193
200
|
@caches_init = true
|
194
201
|
end
|
195
202
|
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
module Organization
|
4
|
+
class PeopleAnalytics < Eco::API::Organization::People
|
5
|
+
include Eco::Data::FuzzyMatch
|
6
|
+
|
7
|
+
# @!group Helpers
|
8
|
+
|
9
|
+
# @!endgroup
|
10
|
+
|
11
|
+
# @!group Searchers
|
12
|
+
|
13
|
+
# It gathers those that have the same `email`
|
14
|
+
# @return [Hash] where `keys` are `email`s and `values` an `Array<Person>`
|
15
|
+
def repeated_emails
|
16
|
+
init_caches
|
17
|
+
@by_email.select do |email, people|
|
18
|
+
people.count > 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @!endgroup
|
23
|
+
|
24
|
+
# @!group Analysers
|
25
|
+
|
26
|
+
# TODO: Sort results by `results.first.methods`
|
27
|
+
def similarity(**options)
|
28
|
+
each_with_object({}) do |person, results|
|
29
|
+
results[person.id] = find_all_with_score(person, **options)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
def print_analysis(threshold)
|
35
|
+
similarity.each do |id, results|
|
36
|
+
msg = results.results.select do |result|
|
37
|
+
result.threshold?(threshold)
|
38
|
+
end.map do |result|
|
39
|
+
result.print
|
40
|
+
end.join("\n ")
|
41
|
+
|
42
|
+
puts "'#{self[id].identify}':\n " + msg
|
43
|
+
end
|
44
|
+
end
|
45
|
+
# @!endgroup
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def on_change
|
50
|
+
remove_instance_variable(@fuzzy_match)
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|