eco-helpers 0.6.0
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 +7 -0
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/README.md +20 -0
- data/eco-helpers.gemspec +34 -0
- data/lib/eco-helpers.rb +15 -0
- data/lib/eco/api.rb +13 -0
- data/lib/eco/api/common.rb +10 -0
- data/lib/eco/api/common/people.rb +17 -0
- data/lib/eco/api/common/people/base_parser.rb +16 -0
- data/lib/eco/api/common/people/default_parsers.rb +40 -0
- data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +28 -0
- data/lib/eco/api/common/people/default_parsers/date_parser.rb +33 -0
- data/lib/eco/api/common/people/default_parsers/multi_parser.rb +33 -0
- data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +23 -0
- data/lib/eco/api/common/people/default_parsers/select_parser.rb +29 -0
- data/lib/eco/api/common/people/entries.rb +120 -0
- data/lib/eco/api/common/people/person_entry.rb +380 -0
- data/lib/eco/api/common/people/person_factory.rb +114 -0
- data/lib/eco/api/common/people/person_modifier.rb +62 -0
- data/lib/eco/api/common/people/person_parser.rb +140 -0
- data/lib/eco/api/common/people/types.rb +47 -0
- data/lib/eco/api/common/session.rb +15 -0
- data/lib/eco/api/common/session/base_session.rb +46 -0
- data/lib/eco/api/common/session/environment.rb +47 -0
- data/lib/eco/api/common/session/file_manager.rb +90 -0
- data/lib/eco/api/common/session/logger.rb +105 -0
- data/lib/eco/api/common/session/mailer.rb +92 -0
- data/lib/eco/api/common/session/s3_uploader.rb +110 -0
- data/lib/eco/api/common/version_patches.rb +11 -0
- data/lib/eco/api/common/version_patches/external_person.rb +11 -0
- data/lib/eco/api/eco_faker.rb +59 -0
- data/lib/eco/api/organization.rb +13 -0
- data/lib/eco/api/organization/account.rb +23 -0
- data/lib/eco/api/organization/people.rb +118 -0
- data/lib/eco/api/organization/policy_groups.rb +51 -0
- data/lib/eco/api/organization/preferences.rb +28 -0
- data/lib/eco/api/organization/preferences_reference.json +23 -0
- data/lib/eco/api/organization/presets.rb +138 -0
- data/lib/eco/api/organization/presets_backup.rb +220 -0
- data/lib/eco/api/organization/presets_values.json +10 -0
- data/lib/eco/api/organization/tag_tree.rb +134 -0
- data/lib/eco/api/organization_old.rb +73 -0
- data/lib/eco/api/session.rb +180 -0
- data/lib/eco/api/session/batch.rb +132 -0
- data/lib/eco/api/session/batch_job.rb +152 -0
- data/lib/eco/api/session/batch_jobs.rb +131 -0
- data/lib/eco/api/session/batch_status.rb +138 -0
- data/lib/eco/api/session/task.rb +92 -0
- data/lib/eco/api/session_config.rb +179 -0
- data/lib/eco/api/session_config/api.rb +47 -0
- data/lib/eco/api/session_config/apis.rb +78 -0
- data/lib/eco/api/session_config/files.rb +30 -0
- data/lib/eco/api/session_config/logger.rb +54 -0
- data/lib/eco/api/session_config/mailer.rb +65 -0
- data/lib/eco/api/session_config/people.rb +89 -0
- data/lib/eco/api/session_config/s3_bucket.rb +62 -0
- data/lib/eco/api/session_config/use_cases.rb +30 -0
- data/lib/eco/api/usecases.rb +12 -0
- data/lib/eco/api/usecases/base_case.rb +14 -0
- data/lib/eco/api/usecases/case_data.rb +13 -0
- data/lib/eco/api/usecases/default_cases.rb +53 -0
- data/lib/eco/api/usecases/default_cases/change_email_case.rb +47 -0
- data/lib/eco/api/usecases/default_cases/create_details_case.rb +29 -0
- data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +49 -0
- data/lib/eco/api/usecases/default_cases/delete_case.rb +20 -0
- data/lib/eco/api/usecases/default_cases/email_as_id_case.rb +24 -0
- data/lib/eco/api/usecases/default_cases/hris_case.rb +67 -0
- data/lib/eco/api/usecases/default_cases/new_email_case.rb +26 -0
- data/lib/eco/api/usecases/default_cases/new_id_case.rb +26 -0
- data/lib/eco/api/usecases/default_cases/refresh_presets.rb +25 -0
- data/lib/eco/api/usecases/default_cases/reinvite_case.rb +22 -0
- data/lib/eco/api/usecases/default_cases/remove_account_case.rb +36 -0
- data/lib/eco/api/usecases/default_cases/reset_landing_page_case.rb +24 -0
- data/lib/eco/api/usecases/default_cases/set_default_tag_case.rb +44 -0
- data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +39 -0
- data/lib/eco/api/usecases/default_cases/to_csv_case.rb +36 -0
- data/lib/eco/api/usecases/default_cases/update_details_case.rb +30 -0
- data/lib/eco/api/usecases/default_cases/upsert_account_case.rb +35 -0
- data/lib/eco/api/usecases/use_case.rb +177 -0
- data/lib/eco/api/usecases/use_group.rb +104 -0
- data/lib/eco/cli.rb +9 -0
- data/lib/eco/cli/input.rb +109 -0
- data/lib/eco/cli/input_multi.rb +137 -0
- data/lib/eco/cli/root.rb +8 -0
- data/lib/eco/cli/session.rb +9 -0
- data/lib/eco/cli/session/batch.rb +9 -0
- data/lib/eco/common.rb +7 -0
- data/lib/eco/common/base_cli.rb +116 -0
- data/lib/eco/common/language.rb +9 -0
- data/lib/eco/data.rb +9 -0
- data/lib/eco/data/crypto.rb +7 -0
- data/lib/eco/data/crypto/encryption.rb +318 -0
- data/lib/eco/data/files.rb +10 -0
- data/lib/eco/data/files/directory.rb +93 -0
- data/lib/eco/data/files/file_pattern.rb +32 -0
- data/lib/eco/data/files/helpers.rb +90 -0
- data/lib/eco/data/mapper.rb +54 -0
- data/lib/eco/data/random.rb +10 -0
- data/lib/eco/data/random/distribution.rb +133 -0
- data/lib/eco/data/random/fake.rb +320 -0
- data/lib/eco/data/random/values.rb +80 -0
- data/lib/eco/language.rb +12 -0
- data/lib/eco/language/curry.rb +28 -0
- data/lib/eco/language/hash_transform.rb +68 -0
- data/lib/eco/language/hash_transform_modifier.rb +114 -0
- data/lib/eco/language/match.rb +30 -0
- data/lib/eco/language/match_modifier.rb +190 -0
- data/lib/eco/language/models.rb +11 -0
- data/lib/eco/language/models/attribute_parser.rb +38 -0
- data/lib/eco/language/models/collection.rb +181 -0
- data/lib/eco/language/models/modifier.rb +68 -0
- data/lib/eco/language/models/wrap.rb +114 -0
- data/lib/eco/language/values_at.rb +159 -0
- data/lib/eco/lexic/dictionary.rb +33 -0
- data/lib/eco/lexic/dictionary/dictionary.txt +355484 -0
- data/lib/eco/lexic/dictionary/tags.json +38 -0
- data/lib/eco/scripting.rb +30 -0
- data/lib/eco/scripting/README.md +11 -0
- data/lib/eco/scripting/arguments.rb +40 -0
- data/lib/eco/tester.rb +97 -0
- data/lib/eco/version.rb +3 -0
- metadata +325 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Eco
|
|
2
|
+
module Language
|
|
3
|
+
module Models
|
|
4
|
+
|
|
5
|
+
class AttributeParser
|
|
6
|
+
|
|
7
|
+
attr_reader :attr
|
|
8
|
+
|
|
9
|
+
def initialize(attr, dependencies: {})
|
|
10
|
+
@attr = attr
|
|
11
|
+
@dependencies = dependencies
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def def_parser(&block)
|
|
15
|
+
@parser = block
|
|
16
|
+
self
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def def_serializer(&block)
|
|
20
|
+
@serializer = block
|
|
21
|
+
self
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def parse(source, dependencies: {})
|
|
25
|
+
raise "There is no parser for this attribue '#{attr}'" if !@parser
|
|
26
|
+
@parser.call(source, @dependencies.merge(dependencies), attr)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def serialize(object, dependencies: {})
|
|
30
|
+
raise "There is no serializer for this attribue '#{attr}'" if !@serializer
|
|
31
|
+
@serializer.call(object, @dependencies.merge(dependencies), attr)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
module Eco
|
|
2
|
+
module Language
|
|
3
|
+
module Models
|
|
4
|
+
class Collection < Array
|
|
5
|
+
|
|
6
|
+
ATTR_PRESENCE_METHODS = ["present", "empty", "present_all?", "present_some?"]
|
|
7
|
+
ATTR_COLLECTION_METHODS = ["exclude", "remove", "attr", "attr?", "attrs", "unique_attrs", "contains"] + ATTR_PRESENCE_METHODS
|
|
8
|
+
|
|
9
|
+
#attr_reader :kclass
|
|
10
|
+
|
|
11
|
+
def initialize(data = [], klass:, factory: nil, handy: Eco::Common::Language.new)
|
|
12
|
+
raise "Raise klass required, given: #{klass}" if !klass
|
|
13
|
+
@klass = klass
|
|
14
|
+
@factory = factory
|
|
15
|
+
@handy = handy
|
|
16
|
+
super(to_klass(data))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def newFrom(data)
|
|
20
|
+
self.class.new(data, klass: @klass, factory: @factory)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def to_c
|
|
24
|
+
Collection.new(self, klass: @klass, factory: @factory)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def new
|
|
28
|
+
self.class.new(self.to_a, klass: @klass, factory: @factory)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def <(value)
|
|
32
|
+
self.clear << value
|
|
33
|
+
on_change
|
|
34
|
+
self
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def <<(value)
|
|
38
|
+
self.concat(into_a(value))
|
|
39
|
+
on_change
|
|
40
|
+
self
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def update(&block)
|
|
44
|
+
newFrom self.map(&block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def delete(value)
|
|
48
|
+
self < self - value
|
|
49
|
+
on_change
|
|
50
|
+
self
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# attr dependant methods
|
|
54
|
+
def exclude(attr, value, modifier = Language::MatchModifier.new)
|
|
55
|
+
newFrom self - self.attr(attr, value, modifier)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def remove(attr, value, modifier = Language::MatchModifier.new)
|
|
59
|
+
self < self.exclude(attr, value, modifier)
|
|
60
|
+
on_change
|
|
61
|
+
self
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def attr(attr, value = true, modifier = Language::MatchModifier.new)
|
|
65
|
+
if !!value == value # boolean?
|
|
66
|
+
self.present(attr, value)
|
|
67
|
+
else
|
|
68
|
+
return newFrom self.select { |object|
|
|
69
|
+
attr_val = fetch_attr(object, attr)
|
|
70
|
+
match?(attr_val, value, modifier)
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def attr?(attr, value = true, modifier = Language::MatchModifier.new)
|
|
76
|
+
modifier = modifier.new.reverse
|
|
77
|
+
if !!value == value # boolean?
|
|
78
|
+
self.present(attr, value).length == self.length
|
|
79
|
+
else
|
|
80
|
+
obj_vals = self.attrs(attr)
|
|
81
|
+
return match?(obj_vals, value, modifier)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def attrs(attr)
|
|
86
|
+
self.map { |object| fetch_attr(object, attr) }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def unique_attrs(attr)
|
|
90
|
+
self.to_h(attr).keys
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def present(attr, flag = true)
|
|
94
|
+
block = ->(o) { !!fetch_attr(o, attr) == !!flag }
|
|
95
|
+
newFrom self.select(&block)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def empty(attr, flag = true)
|
|
99
|
+
self.present(attr, !flag)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def present_all?(attr, flag = true)
|
|
103
|
+
self.present(attr, flag).length == self.length
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def present_some?(attr, flag = true)
|
|
107
|
+
self.present(attr, flag).length > 0
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def contains(attr, value, modifier = Language::MatchModifier.new)
|
|
111
|
+
modifier = modifier.new.pattern
|
|
112
|
+
self.attr(attr, value, modifier)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def group_by(attr)
|
|
116
|
+
#self.to_h(attr)
|
|
117
|
+
return {} if !attr
|
|
118
|
+
self.to_a.group_by { |object| object.method(attr).call }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def to_h(attr)
|
|
122
|
+
return {} if !attr
|
|
123
|
+
self.to_a.group_by { |object| object.method(attr).call }
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# class level methods
|
|
127
|
+
def self.attr_collection (*attrs)
|
|
128
|
+
block = ->(method) { attrs_create_method(attrs, method) }
|
|
129
|
+
ATTR_COLLECTION_METHODS.each(&block)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def self.attr_presence (*attrs)
|
|
133
|
+
block = ->(method) { attrs_create_method(attrs, method) }
|
|
134
|
+
ATTR_PRESENCE_METHODS.each(&block)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def self.attrs_create_method(attrs, method)
|
|
138
|
+
attrs.each do |attr|
|
|
139
|
+
attr = attr.to_s
|
|
140
|
+
if method.include?("attr")
|
|
141
|
+
attr_method = method.sub("attr", attr)
|
|
142
|
+
else
|
|
143
|
+
attr_method = "#{attr}_#{method}"
|
|
144
|
+
end
|
|
145
|
+
define_method attr_method do |*args|
|
|
146
|
+
send(method, attr, *args)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
protected
|
|
152
|
+
|
|
153
|
+
def on_change
|
|
154
|
+
# function to be overriden by children classes
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def into_a(value)
|
|
158
|
+
value = [].push(value) unless value.is_a?(Array)
|
|
159
|
+
value
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
private
|
|
163
|
+
|
|
164
|
+
def match?(*args)
|
|
165
|
+
@handy.match?(*args)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def to_klass(list)
|
|
169
|
+
into_a(list).map do |v|
|
|
170
|
+
v.is_a?(@klass) ? v : @factory&.new(v) || @klass.new(v)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def fetch_attr(object,attr)
|
|
175
|
+
object.method(attr).call
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module Eco
|
|
2
|
+
module Language
|
|
3
|
+
module Models
|
|
4
|
+
class Modifier < Array
|
|
5
|
+
|
|
6
|
+
DEFAULT_MODE = [:default, :none]
|
|
7
|
+
|
|
8
|
+
def initialize(value = [])
|
|
9
|
+
super(into_a(value))
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def new
|
|
13
|
+
self.class.new(self.resolve_mode.to_a)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# MODE MODIFIERS
|
|
17
|
+
# resolve mode
|
|
18
|
+
def mode
|
|
19
|
+
resolve_mode
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def <(value)
|
|
23
|
+
self.clear << value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def <<(value)
|
|
27
|
+
self.concat(into_a(value))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def flush_mode
|
|
31
|
+
self < self.mode
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def default(value)
|
|
35
|
+
#self.unshift(value)
|
|
36
|
+
reset
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def reset
|
|
40
|
+
self < DEFAULT_MODE.first
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def default?
|
|
44
|
+
(mode - DEFAULT_MODE).length == 0
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
protected
|
|
48
|
+
|
|
49
|
+
def resolve_mode
|
|
50
|
+
self.to_a
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def resolve (ms, flags)
|
|
54
|
+
# later modifiers have precedence
|
|
55
|
+
flag = (ms & flags).last
|
|
56
|
+
ms = (ms - flags).push(flag) unless !flag
|
|
57
|
+
return ms
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def into_a(value)
|
|
61
|
+
value = [].push(value) unless value.is_a?(Array)
|
|
62
|
+
value
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Eco
|
|
2
|
+
module Language
|
|
3
|
+
module Models
|
|
4
|
+
class Wrap
|
|
5
|
+
|
|
6
|
+
attr_reader :setters, :getters
|
|
7
|
+
attr_reader :object
|
|
8
|
+
|
|
9
|
+
def initialize(object = nil, setters: [], getters: [])
|
|
10
|
+
@object = object
|
|
11
|
+
self.setters = setters
|
|
12
|
+
self.getters = getters
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def getters=(value)
|
|
16
|
+
@getters = into_a(value)
|
|
17
|
+
@wgetters = wrap_object(@object, @getters)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def setters=(value)
|
|
21
|
+
@setters = into_a(value)
|
|
22
|
+
@wsetters = wrap_object(@object, @setters)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def object=(value)
|
|
26
|
+
@object = value
|
|
27
|
+
@wgetters = wrap_object(@object, @getters)
|
|
28
|
+
@wsetters = wrap_object(@object, @setters)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def <<(value = [])
|
|
32
|
+
value = into_a(value)
|
|
33
|
+
@wsetters.each_with_index.map do |set, i|
|
|
34
|
+
args = into_a(value[i])
|
|
35
|
+
set.call(*args)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def row(value = (miss = true; []))
|
|
40
|
+
value = into_a(value)
|
|
41
|
+
@wgetters.each_with_index.map do |get, i|
|
|
42
|
+
args = into_a(value[i])
|
|
43
|
+
get.call(*args) unless miss
|
|
44
|
+
get.call
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def wrap_object(object = nil, ops = [])
|
|
49
|
+
object = object || @object
|
|
50
|
+
return [] unless !!object
|
|
51
|
+
into_a(ops).map do |op|
|
|
52
|
+
cop = required_parameters?(op) ? curry(op) : op
|
|
53
|
+
->(*args) {
|
|
54
|
+
args.unshift(object);
|
|
55
|
+
#puts "calling wop: #{cop}, with args: #{args}, object: #{object}"
|
|
56
|
+
cop[*args] #rescue nil
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
module Test
|
|
62
|
+
class A
|
|
63
|
+
attr_accessor :a, :e
|
|
64
|
+
def initialize(val)
|
|
65
|
+
self.a = val
|
|
66
|
+
@e = 2
|
|
67
|
+
end
|
|
68
|
+
def exp
|
|
69
|
+
@a**@e
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.test()
|
|
75
|
+
# setters
|
|
76
|
+
soa = ->(o,v) { o.a = v }
|
|
77
|
+
soe = ->(o,v) { o.e = v }
|
|
78
|
+
# getters
|
|
79
|
+
goa = ->(o) { o.a }
|
|
80
|
+
goe = ->(o) { o.e }
|
|
81
|
+
goex = ->(o) { o.exp }
|
|
82
|
+
|
|
83
|
+
# arrays
|
|
84
|
+
setters = [soa, soe ]
|
|
85
|
+
getters = [goa, goe, goex]
|
|
86
|
+
|
|
87
|
+
a = Test::A.new(3)
|
|
88
|
+
b = Test::A.new(5)
|
|
89
|
+
w = self.new(a, setters: setters, getters: getters)
|
|
90
|
+
|
|
91
|
+
puts "before check -> a: #{a.a}; e: #{a.e}; exp: #{a.exp}"
|
|
92
|
+
# launch setters
|
|
93
|
+
w << [4, 2]
|
|
94
|
+
puts "after setters -> a: #{a.a}; e: #{a.e}; exp: #{a.exp}"
|
|
95
|
+
# launch getters
|
|
96
|
+
a, e, exp = w.row
|
|
97
|
+
puts "from getters(a) -> a: #{a}; e: #{e}; exp: #{exp}"
|
|
98
|
+
# switch object
|
|
99
|
+
w.object = b
|
|
100
|
+
# launch getters
|
|
101
|
+
a, e, exp = w.row
|
|
102
|
+
puts "from getters(b) -> a: #{a}; e: #{e}; exp: #{exp}"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
private
|
|
106
|
+
|
|
107
|
+
def into_a(value)
|
|
108
|
+
value = [].push(value) unless value.is_a?(Array)
|
|
109
|
+
value
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
module Eco
|
|
2
|
+
module Language
|
|
3
|
+
|
|
4
|
+
def to_key(pr)
|
|
5
|
+
pr.is_a?(Hash) ? pr.keys.first : pr
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def to_value(pr)
|
|
9
|
+
pr.is_a?(Hash) ? pr.values.first : pr
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def values_at(object, *attrs, **kattrs)
|
|
13
|
+
all_params = attrs + kattrs.map {|k,v| {k => v} }
|
|
14
|
+
return object.values_at(*all_params) if object.is_a?(Hash)
|
|
15
|
+
all_keys = all_params.map { |pr| to_key(pr) }
|
|
16
|
+
arguments = all_params.each_with_index.map { |pr, i| pr.values[0] if pr.is_a?(Hash)}
|
|
17
|
+
#puts "all_keys: #{all_keys}; arguments: #{arguments}"
|
|
18
|
+
values = all_keys.each_with_index.map do |k, i|
|
|
19
|
+
a = k; v = []
|
|
20
|
+
v = arguments[i] if all_params[i].is_a?(Hash) # with params
|
|
21
|
+
attr_method = get_accessor(object, a)[object, a] rescue nil
|
|
22
|
+
#puts "attr: #{a} - method: #{attr_method}"
|
|
23
|
+
next if !attr_method
|
|
24
|
+
args = v.is_a?(Array) ? v : [].push(v)
|
|
25
|
+
attr_method = curry(attr_method) if required_parameters?(attr_method)
|
|
26
|
+
# final call to the method
|
|
27
|
+
#puts "args: #{args}"
|
|
28
|
+
value = attr_method[*args] # rescue nil
|
|
29
|
+
value = nil if value.is_a?(Proc)
|
|
30
|
+
value
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# adapted from: https://stackoverflow.com/a/16908153/4352306
|
|
35
|
+
def get_accessor(object, attr, accessors: [])
|
|
36
|
+
accessors.push( ->(obj, att) { object.method(att) } )
|
|
37
|
+
#accessors.push( ->(obj, att) { object[att] } )
|
|
38
|
+
accessors.reduce(nil) { |chosen, acc| chosen ? chosen :
|
|
39
|
+
(acc[object, attr] && acc rescue nil) || chosen }
|
|
40
|
+
#accessors.reduce(nil) { |chosen, acc|
|
|
41
|
+
# puts "attr: #{attr} => current: #{acc}"
|
|
42
|
+
# chosen ? chosen : (acc[object, attr] && acc rescue nil) || chosen
|
|
43
|
+
# puts "attr: #{attr} => after check - chosen: #{chosen}"
|
|
44
|
+
# chosen
|
|
45
|
+
# }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# enables dot notation to do object nesting access
|
|
49
|
+
def values_at_dot (object, *attrs, curry: false, debug: false, **kattrs)
|
|
50
|
+
all_params = attrs + kattrs.map {|k,v| {k => v} }
|
|
51
|
+
return object.values_at(*all_params) if object.is_a?(Hash)
|
|
52
|
+
|
|
53
|
+
to_s = ->(k) { ((k.to_s rescue k) || key) }
|
|
54
|
+
to_sym = ->(k) { ((k.to_sym rescue k) || key) }
|
|
55
|
+
dotted = ->(k) { to_s[k].include?('.') }
|
|
56
|
+
pdotted = ->(pr) { dotted[to_key(pr)] }
|
|
57
|
+
haccess = ->(dp) { # prepare call
|
|
58
|
+
k = dp
|
|
59
|
+
k, v = [dp.keys.first, dp.values.first] if (hash = dp.is_a?(Hash))
|
|
60
|
+
kf, kr = [ (ss = to_s[k].split('.')).first , ss.slice(1)]
|
|
61
|
+
nxt_cll = hash ? {kr => v} : kr
|
|
62
|
+
{k => {'a' => kf, 'v' => nxt_cll }}
|
|
63
|
+
}
|
|
64
|
+
all_keys = all_params.map { |pr| to_key(pr) }
|
|
65
|
+
hash_params = all_params.reduce({}) { |h,pr| h.merge!(pr) if pr.is_a?(Hash); h }
|
|
66
|
+
dot_params = all_params.select { |pr| pdotted[pr] }
|
|
67
|
+
dot_keys = dot_params.map { |dp| to_key(dp) }
|
|
68
|
+
dot_wrappers = dot_params.reduce({}) { |h,dp| h.merge(haccess[dp]) }
|
|
69
|
+
|
|
70
|
+
if debug
|
|
71
|
+
pp "object : #{object}"
|
|
72
|
+
pp "all_params: #{all_params}"
|
|
73
|
+
pp "dot_keys : #{dot_keys}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
values = all_keys.map do |k|
|
|
77
|
+
a = k; v = []
|
|
78
|
+
puts "key: #{k}" if debug
|
|
79
|
+
case true
|
|
80
|
+
when dot_keys.include?(k) # dotted (recursive)
|
|
81
|
+
dot = dot_wrappers[k]
|
|
82
|
+
a, v = dot.values_at('a', 'v')
|
|
83
|
+
when hash_params.key?(k) # no dotted, with params
|
|
84
|
+
v = hash_params[k]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
attr_method = get_accessor(object, a)[object, a] rescue nil
|
|
88
|
+
next if !attr_method
|
|
89
|
+
|
|
90
|
+
args = v.is_a?(Array) ? v : [].push(v)
|
|
91
|
+
attr_method = curry(attr_method) if required_parameters?(attr_method)
|
|
92
|
+
if dot_keys.include?(k) # recurse (dotted)
|
|
93
|
+
args.push({ curry: curry, debug: debug })
|
|
94
|
+
value = values_at(attr_method.call, *args).first
|
|
95
|
+
else # final call to the method
|
|
96
|
+
value = attr_method[*args] # rescue nil
|
|
97
|
+
puts "value: #{value}" if debug
|
|
98
|
+
end
|
|
99
|
+
value = nil if !curry && value.is_a?(Proc)
|
|
100
|
+
value
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
module Test
|
|
106
|
+
class A
|
|
107
|
+
attr_reader :ops, :cops
|
|
108
|
+
def initialize(val)
|
|
109
|
+
@ops = val
|
|
110
|
+
end
|
|
111
|
+
def mops
|
|
112
|
+
'm-' + @ops
|
|
113
|
+
end
|
|
114
|
+
def cops=(value)
|
|
115
|
+
@ops = value
|
|
116
|
+
end
|
|
117
|
+
def rops(val)
|
|
118
|
+
@ops + " there we go with '#{val}' !!"
|
|
119
|
+
end
|
|
120
|
+
def xops(val, xop:)
|
|
121
|
+
@ops + " #{val}!! Xops do the trick with '#{xop}'."
|
|
122
|
+
end
|
|
123
|
+
private
|
|
124
|
+
def gops
|
|
125
|
+
'g+' + @ops
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
class B
|
|
129
|
+
attr_accessor :a, :c
|
|
130
|
+
def initialize(a)
|
|
131
|
+
@a = A.new(a)
|
|
132
|
+
end
|
|
133
|
+
def c=(value)
|
|
134
|
+
@c = value
|
|
135
|
+
end
|
|
136
|
+
def bofs(v1, v2:)
|
|
137
|
+
"#{v1} #{v2} with #{@c}"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def self.test_values_at
|
|
143
|
+
h = {'pops' => 'aghr!', pops: 5, 'nops' => 'nope!'}
|
|
144
|
+
a = Test::A.new('hello!')
|
|
145
|
+
b = Test::B.new('bye')
|
|
146
|
+
b.c = 'cheese'
|
|
147
|
+
|
|
148
|
+
pp Handy.values_at(h, 'nops', :pops)
|
|
149
|
+
pp Handy.values_at(a, 'rops', 'mops', rops: 'EVERY', xops: ['Dear', xop: 'SOMETHING BETTER'])
|
|
150
|
+
pp Handy.values_at(a, 'mops', 'gops', rops: 'EVERY THING')
|
|
151
|
+
|
|
152
|
+
pp Handy.values_at_dot(b, 'c', 'bofs' => ['stranberry', v2: 'combines'], 'a.rops': 'DOTTED CALL')
|
|
153
|
+
pp "+" * 60
|
|
154
|
+
pp Handy.values_at_dot(b, 'c', 'bofs' => ['stranberry', v2: 'combines'], debug: true, 'a.rops': 'DOTTED CALL')
|
|
155
|
+
pp "+" * 60
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
|
159
|
+
end
|