eco-helpers 1.3.1 → 1.3.2
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/lib/eco-helpers.rb +1 -0
- data/lib/eco/api/common/people.rb +1 -0
- data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +1 -1
- data/lib/eco/api/common/people/default_parsers/csv_parser.rb +4 -1
- data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +1 -1
- data/lib/eco/api/common/people/entries.rb +10 -0
- data/lib/eco/api/common/people/supervisor_helpers.rb +142 -0
- data/lib/eco/cli/config/default/filters.rb +4 -4
- data/lib/eco/cli/config/default/options.rb +16 -0
- data/lib/eco/csv.rb +33 -0
- data/lib/eco/csv/table.rb +79 -0
- data/lib/eco/language/models/collection.rb +3 -4
- data/lib/eco/version.rb +1 -1
- metadata +24 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa39fb0038e03d65a129a3d7df06f5c3fba60518ef847cd89cfe0d973f27065e
|
4
|
+
data.tar.gz: f22d6d27a952af99e4f84eb1ed29a8b930d7226f0a67d60c86f6eabb4a15715f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 070ee0c500e334ef8bf149bdf3ec24fd20480a16a3b4742f25247fccd09a8ef476a3bdfcfb45119a4fa37dc1c0dbe415cf53de2fa6ecd4722fa81f65c3762450
|
7
|
+
data.tar.gz: c4456bbbfd19b4e03734f6dd9b388087c7a7aee44dba138ec2aa1dfc78ceff0024c222589d5e9857561b25ef730faf3f9e8008dfb5d4dd006cfaa47c15c197a7
|
data/lib/eco-helpers.rb
CHANGED
@@ -15,5 +15,6 @@ require_relative 'people/person_parser'
|
|
15
15
|
require_relative 'people/default_parsers'
|
16
16
|
require_relative 'people/person_entry_attribute_mapper'
|
17
17
|
require_relative 'people/person_entry'
|
18
|
+
require_relative 'people/supervisor_helpers'
|
18
19
|
require_relative 'people/entries'
|
19
20
|
require_relative 'people/entry_factory'
|
@@ -9,7 +9,10 @@ module Eco
|
|
9
9
|
@parsers.define_attribute(:csv, dependencies: @options) do |parser|
|
10
10
|
parser.def_parser do |data, deps|
|
11
11
|
arr_hash = []
|
12
|
-
CSV.parse(data, headers: true).
|
12
|
+
CSV.parse(data, headers: true, skip_blanks: true).reject do |row|
|
13
|
+
values = row.to_hash.values
|
14
|
+
values.all?(&:nil?) || values.map(&:to_s).all?(&:empty?)
|
15
|
+
end.each do |row|
|
13
16
|
row_hash = row.headers.uniq.each_with_object({}) do |attr, hash|
|
14
17
|
value = row[attr]
|
15
18
|
hash[attr] = value.to_s.empty?? nil : value
|
@@ -8,7 +8,7 @@ module Eco
|
|
8
8
|
def process
|
9
9
|
@parsers.define_attribute(:number, dependencies: @options) do |parser|
|
10
10
|
parser.def_parser do |value, deps|
|
11
|
-
value = value.to_s.strip
|
11
|
+
value = value.to_s.strip.empty? ? nil : (value.to_f rescue nil)
|
12
12
|
end.def_serializer do |value|
|
13
13
|
value.is_a?(Array) ? value.map { |v| v.to_s } : value.to_s
|
14
14
|
end
|
@@ -10,11 +10,20 @@ module Eco
|
|
10
10
|
|
11
11
|
alias_method :entries, :to_a
|
12
12
|
|
13
|
+
include Eco::API::Common::People::SupervisorHelpers
|
14
|
+
|
13
15
|
def initialize(data = [], klass:, factory:)
|
14
16
|
super(data, klass: klass, factory: factory)
|
15
17
|
@caches_init = false
|
16
18
|
end
|
17
19
|
|
20
|
+
# Override `each` to make it work with supervisor hiearchy
|
21
|
+
def each(params: {}, &block)
|
22
|
+
return to_enum(:each) unless block
|
23
|
+
@array_supers = sort_by_supervisors(@items) unless @caches_init
|
24
|
+
@array_supers.each(&block)
|
25
|
+
end
|
26
|
+
|
18
27
|
def [](id_or_ext)
|
19
28
|
id(id_or_ext) || external_id(id_or_ext)
|
20
29
|
end
|
@@ -96,6 +105,7 @@ module Eco
|
|
96
105
|
@by_id = to_h
|
97
106
|
@by_external_id = to_h('external_id')
|
98
107
|
@by_email = to_h('email')
|
108
|
+
@array_supers = sort_by_supervisors(@items)
|
99
109
|
@caches_init = true
|
100
110
|
end
|
101
111
|
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
module Common
|
4
|
+
module People
|
5
|
+
# Used with `Enumerable` of objects that have the following methods:
|
6
|
+
# * `supervisor_id`
|
7
|
+
# * `external_id`
|
8
|
+
# * `id`
|
9
|
+
module SupervisorHelpers
|
10
|
+
|
11
|
+
# Reorders as follows:
|
12
|
+
# 1. supervisors, people with no supervisor or where their supervisor not present
|
13
|
+
# 2. subordinates
|
14
|
+
def sort_by_supervisors(values, supervisors_first: true)
|
15
|
+
raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
|
16
|
+
return [] unless values && values.is_a?(Enumerable)
|
17
|
+
roam = Proc.new do |tree|
|
18
|
+
[].tap do |out|
|
19
|
+
sub_outs = tree.empty?? [] : tree.map {|sup, subtree| roam.call(subtree)}
|
20
|
+
tree.each do |sup, subtree|
|
21
|
+
sout = subtree.empty?? [] :roam.call(subtree)
|
22
|
+
supervisors_first ? sout.unshift(sup) : sout.push(sup)
|
23
|
+
out.concat(sout)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
roam.call(supervisors_tree(values))
|
29
|
+
end
|
30
|
+
|
31
|
+
def tree_to_str(tree, lev: 0)
|
32
|
+
raise "Required Hash tree structure. Given: #{tree.class}" unless tree.is_a?(Hash)
|
33
|
+
"".tap do |str|
|
34
|
+
tree.each do |entry, subtree|
|
35
|
+
str << "#{" " * lev}+-- #{entry.id || entry.external_id}\n"
|
36
|
+
str << tree_to_str(subtree, lev: lev + 1) unless !subtree || subtree.empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def print_tree(tree, lev: 0)
|
42
|
+
puts tree_to_str(tree)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Generates a `Hash` tree structure, where:
|
46
|
+
# * **keys** are nodes
|
47
|
+
# * **values** are `Hash` subtree structures of `key` subordinates
|
48
|
+
# @note it is resilient to cyclic supervisors (it will just add the last at the top)
|
49
|
+
# @param values [Enumerable<Object>] of objects with methods:
|
50
|
+
# `id`, `external_id` and `supervisor_id`
|
51
|
+
# @return [Hash] the tree structure
|
52
|
+
def supervisors_tree(values)
|
53
|
+
raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
|
54
|
+
return {} unless values && values.is_a?(Enumerable)
|
55
|
+
idx = get_super_indexes(values)
|
56
|
+
|
57
|
+
processed = []
|
58
|
+
subtree = Proc.new do |entry, level, toptree|
|
59
|
+
if processed.include?(entry)
|
60
|
+
next {} unless toptree.key?(entry) && level > 0
|
61
|
+
# needs to be moved as a child
|
62
|
+
subnodes = toptree.delete(entry)
|
63
|
+
processed.delete(entry)
|
64
|
+
end
|
65
|
+
|
66
|
+
subnodes ||= {}.tap do |tree|
|
67
|
+
subs = idx[:subordinates].call(entry)
|
68
|
+
processed.push(entry)
|
69
|
+
next nil unless subs && !subs.empty?
|
70
|
+
subs.each do |sub|
|
71
|
+
sub_tree = subtree.call(sub, level + 1, toptree)
|
72
|
+
tree.merge!(sub_tree)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
{entry => subnodes}
|
77
|
+
end
|
78
|
+
|
79
|
+
{}.tap do |tree|
|
80
|
+
idx[:by_sup].keys.each do |sup_id|
|
81
|
+
if sup = idx[:supers][sup_id]
|
82
|
+
tree.merge!(subtree.call(sup, 0, tree))
|
83
|
+
else
|
84
|
+
idx[:by_sup][sup_id].each do |sub|
|
85
|
+
tree.merge!(subtree.call(sub, 0, tree))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def get_super_indexes(values)
|
95
|
+
raise "Expected non hash Enumerable. Given: #{values.class}" if values.is_a?(Hash)
|
96
|
+
{}.tap do |indexes|
|
97
|
+
indexes[:by_id] = values.map do |e|
|
98
|
+
e.id && [e.id, e]
|
99
|
+
end.compact.to_h
|
100
|
+
indexes[:by_ext] = values.map do |e|
|
101
|
+
e.external_id && [e.external_id, e]
|
102
|
+
end.compact.to_h
|
103
|
+
|
104
|
+
indexes[:by_sup] = {}.tap do |by_s|
|
105
|
+
values.group_by do |e|
|
106
|
+
e.supervisor_id
|
107
|
+
end.tap do |by_sup|
|
108
|
+
by_s[nil] = by_sup.delete(nil) if by_sup.key?(nil)
|
109
|
+
by_s.merge!(by_sup)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
indexes[:supers] = {}.tap do |sups|
|
114
|
+
indexes[:by_ext].select do |ext, e|
|
115
|
+
ext && indexes[:by_sup].key?(ext)
|
116
|
+
end.tap {|found| sups.merge!(found)}
|
117
|
+
indexes[:by_id].select do |id, e|
|
118
|
+
id && indexes[:by_sup].key?(id)
|
119
|
+
end.tap {|found| sups.merge!(found)}
|
120
|
+
end
|
121
|
+
|
122
|
+
indexes[:is_super] = Proc.new do |entry|
|
123
|
+
!!(indexes[:supers][entry.id] || indexes[:supers][entry.external_id])
|
124
|
+
end
|
125
|
+
|
126
|
+
indexes[:subordinates] = Proc.new do |entry|
|
127
|
+
subs = nil
|
128
|
+
if sup = indexes[:supers][entry.id] || indexes[:supers][entry.external_id]
|
129
|
+
subs ||= indexes[:by_sup][sup.id] unless !sup.id
|
130
|
+
subs ||= indexes[:by_sup][sup.external_id] unless !sup.external_id
|
131
|
+
end
|
132
|
+
subs
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -56,13 +56,13 @@ ASSETS.cli.config do |cnf|
|
|
56
56
|
end
|
57
57
|
|
58
58
|
options.deep_merge!(people: {filter: {details: {schema_id: sch_id}}})
|
59
|
-
session.logger.info("Filtering
|
60
|
-
|
61
|
-
session.schema = sch_id
|
62
|
-
|
59
|
+
session.logger.info("Filtering people entries with schema #{session.schemas.to_name(sch_id)}")
|
60
|
+
|
63
61
|
filtered = people.select do |person|
|
64
62
|
person.details && (person.details.schema_id == sch_id)
|
65
63
|
end
|
64
|
+
session.logger.info("Filtered #{filtered.count} people out of #{people.count} total")
|
65
|
+
|
66
66
|
people.newFrom filtered
|
67
67
|
end
|
68
68
|
|
@@ -1,6 +1,22 @@
|
|
1
1
|
ASSETS.cli.config do |cnf|
|
2
2
|
cnf.options_set do |options_set, options|
|
3
3
|
|
4
|
+
options_set.add("-schema-id") do |options, session|
|
5
|
+
sch_name = SCR.get_arg("-schema-id", with_param: true)
|
6
|
+
sch_id = session.schemas.to_id(sch_name)
|
7
|
+
|
8
|
+
unless sch_id
|
9
|
+
msg = "You need to specify a schema id or name. '#{sch_id}' does not exist"
|
10
|
+
session.logger.error(msg)
|
11
|
+
exit(1)
|
12
|
+
end
|
13
|
+
|
14
|
+
options.deep_merge!(people: {filter: {details: {schema_id: sch_id}}})
|
15
|
+
session.logger.info("Setting schema #{session.schemas.to_name(sch_id)}")
|
16
|
+
|
17
|
+
session.schema = sch_id
|
18
|
+
end
|
19
|
+
|
4
20
|
options_set.add("-entries-from") do |options, session|
|
5
21
|
options.deep_merge!(input: {entries_from: true})
|
6
22
|
end
|
data/lib/eco/csv.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module Eco
|
4
|
+
class CSV < ::CSV
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def parse(data, **kargs, &block)
|
9
|
+
kargs = {headers: true, skip_blanks: true}.merge(kargs)
|
10
|
+
out = super(data, **kargs, &block).reject do |row|
|
11
|
+
values = row.to_hash.values
|
12
|
+
values.all?(&:nil?) || values.map(&:to_s).all?(&:empty?)
|
13
|
+
end
|
14
|
+
Eco::CSV::Table.new(out)
|
15
|
+
end
|
16
|
+
|
17
|
+
def read(file, **kargs)
|
18
|
+
coding = Eco::API::Common::Session::FileManager.encoding(file)
|
19
|
+
kargs = {headers: true, skip_blanks: true, encoding: coding}.merge(kargs)
|
20
|
+
out = super(file, **kargs).reject do |row|
|
21
|
+
values = row.to_hash.values
|
22
|
+
values.all?(&:nil?) || values.map(&:to_s).all?(&:empty?)
|
23
|
+
end
|
24
|
+
Eco::CSV::Table.new(out)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
require_relative 'csv/table'
|
@@ -0,0 +1,79 @@
|
|
1
|
+
|
2
|
+
module Eco
|
3
|
+
class CSV
|
4
|
+
class Table < ::CSV::Table
|
5
|
+
|
6
|
+
# @param ary_arrays [Array<Row>, Array<Array>, Eco::CSV::Table, ::CSV::Table]
|
7
|
+
# - when `Array<Array>` => all `rows` as arrays where first array is the **header**
|
8
|
+
def initialize(input)
|
9
|
+
super(to_rows_array(input))
|
10
|
+
end
|
11
|
+
|
12
|
+
# @return [Array<::CSV::Row>]
|
13
|
+
def rows
|
14
|
+
[].tap do |out|
|
15
|
+
self.each {|row| out << row}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [Integer] total number of rows not including the header
|
20
|
+
def length
|
21
|
+
to_a.length - 1
|
22
|
+
end
|
23
|
+
|
24
|
+
# @return [Array<Array>] each array is the column header followed by its values
|
25
|
+
def columns
|
26
|
+
to_a.transpose
|
27
|
+
end
|
28
|
+
|
29
|
+
# Adds a new column at the end
|
30
|
+
# @param header_name [String] header of the new column
|
31
|
+
# @return [Eco::CSV::Table] with a new empty column
|
32
|
+
def add_column(header_name)
|
33
|
+
new_col = Array.new(length).unshift(header_name)
|
34
|
+
columns_to_table(columns.push(new_col))
|
35
|
+
end
|
36
|
+
|
37
|
+
# @note it will override columns with same header name
|
38
|
+
# @return [Hash] keys are headers, values are arrays
|
39
|
+
def columns_hash
|
40
|
+
columns.map do |col|
|
41
|
+
[col.first, col[1..-1]]
|
42
|
+
end.to_h
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def columns_to_table(columns_array)
|
48
|
+
data = to_rows_array(columns_array.transpose)
|
49
|
+
self.class.new(data)
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_rows_array(data)
|
53
|
+
case data
|
54
|
+
when Array
|
55
|
+
return data unless data.length > 0
|
56
|
+
if data.first.is_a?(::CSV::Row)
|
57
|
+
data
|
58
|
+
elsif data.first.is_a?(Array)
|
59
|
+
headers = data.shift
|
60
|
+
data.map do |arr_row|
|
61
|
+
CSV::Row.new(headers, arr_row)
|
62
|
+
end.compact
|
63
|
+
else
|
64
|
+
raise "Expected data that can be transformed into Array<Array>"
|
65
|
+
end
|
66
|
+
when ::CSV::Table
|
67
|
+
to_rows_array(data.to_a)
|
68
|
+
when Hash
|
69
|
+
# hash of columns header as key and column array as value
|
70
|
+
rows_arrays = [a.keys].concat(a.values.first.zip(*a.values[1..-1]))
|
71
|
+
to_rows_array(data.keys)
|
72
|
+
else
|
73
|
+
raise "Input type not supported. Given: #{data.class}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -154,10 +154,9 @@ module Eco
|
|
154
154
|
self.attr(attr, value, modifier)
|
155
155
|
end
|
156
156
|
|
157
|
-
def group_by(attr)
|
158
|
-
to_h(attr)
|
159
|
-
|
160
|
-
#self.to_a.group_by { |object| object.method(attr).call }
|
157
|
+
def group_by(attr = nil, &block)
|
158
|
+
return to_h(attr) if attr
|
159
|
+
to_a.group_by(&block) if block
|
161
160
|
end
|
162
161
|
|
163
162
|
def to_h(attr)
|
data/lib/eco/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eco-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oscar Segura
|
@@ -82,22 +82,22 @@ dependencies:
|
|
82
82
|
name: redcarpet
|
83
83
|
requirement: !ruby/object:Gem::Requirement
|
84
84
|
requirements:
|
85
|
-
- - ">="
|
86
|
-
- !ruby/object:Gem::Version
|
87
|
-
version: 3.5.0
|
88
85
|
- - "~>"
|
89
86
|
- !ruby/object:Gem::Version
|
90
87
|
version: '3.5'
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 3.5.0
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- - ">="
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
version: 3.5.0
|
98
95
|
- - "~>"
|
99
96
|
- !ruby/object:Gem::Version
|
100
97
|
version: '3.5'
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 3.5.0
|
101
101
|
- !ruby/object:Gem::Dependency
|
102
102
|
name: ecoportal-api
|
103
103
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,42 +142,42 @@ dependencies:
|
|
142
142
|
name: aws-sdk-ses
|
143
143
|
requirement: !ruby/object:Gem::Requirement
|
144
144
|
requirements:
|
145
|
-
- - ">="
|
146
|
-
- !ruby/object:Gem::Version
|
147
|
-
version: 1.14.0
|
148
145
|
- - "~>"
|
149
146
|
- !ruby/object:Gem::Version
|
150
147
|
version: '1.14'
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: 1.14.0
|
151
151
|
type: :runtime
|
152
152
|
prerelease: false
|
153
153
|
version_requirements: !ruby/object:Gem::Requirement
|
154
154
|
requirements:
|
155
|
-
- - ">="
|
156
|
-
- !ruby/object:Gem::Version
|
157
|
-
version: 1.14.0
|
158
155
|
- - "~>"
|
159
156
|
- !ruby/object:Gem::Version
|
160
157
|
version: '1.14'
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: 1.14.0
|
161
161
|
- !ruby/object:Gem::Dependency
|
162
162
|
name: dotenv
|
163
163
|
requirement: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
|
-
- - ">="
|
166
|
-
- !ruby/object:Gem::Version
|
167
|
-
version: 2.6.0
|
168
165
|
- - "~>"
|
169
166
|
- !ruby/object:Gem::Version
|
170
167
|
version: '2.6'
|
168
|
+
- - ">="
|
169
|
+
- !ruby/object:Gem::Version
|
170
|
+
version: 2.6.0
|
171
171
|
type: :runtime
|
172
172
|
prerelease: false
|
173
173
|
version_requirements: !ruby/object:Gem::Requirement
|
174
174
|
requirements:
|
175
|
-
- - ">="
|
176
|
-
- !ruby/object:Gem::Version
|
177
|
-
version: 2.6.0
|
178
175
|
- - "~>"
|
179
176
|
- !ruby/object:Gem::Version
|
180
177
|
version: '2.6'
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: 2.6.0
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: net-sftp
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|
@@ -235,6 +235,7 @@ files:
|
|
235
235
|
- lib/eco/api/common/people/person_factory.rb
|
236
236
|
- lib/eco/api/common/people/person_modifier.rb
|
237
237
|
- lib/eco/api/common/people/person_parser.rb
|
238
|
+
- lib/eco/api/common/people/supervisor_helpers.rb
|
238
239
|
- lib/eco/api/common/session.rb
|
239
240
|
- lib/eco/api/common/session/base_session.rb
|
240
241
|
- lib/eco/api/common/session/environment.rb
|
@@ -344,6 +345,8 @@ files:
|
|
344
345
|
- lib/eco/cli/scripting/argument.rb
|
345
346
|
- lib/eco/cli/scripting/arguments.rb
|
346
347
|
- lib/eco/common.rb
|
348
|
+
- lib/eco/csv.rb
|
349
|
+
- lib/eco/csv/table.rb
|
347
350
|
- lib/eco/data.rb
|
348
351
|
- lib/eco/data/crypto.rb
|
349
352
|
- lib/eco/data/crypto/encryption.rb
|
@@ -384,7 +387,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
384
387
|
- !ruby/object:Gem::Version
|
385
388
|
version: '0'
|
386
389
|
requirements: []
|
387
|
-
|
390
|
+
rubyforge_project:
|
391
|
+
rubygems_version: 2.7.6.2
|
388
392
|
signing_key:
|
389
393
|
specification_version: 4
|
390
394
|
summary: eco-helpers to manage people api cases
|