eco-helpers 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +82 -2
  3. data/LICENSE +21 -0
  4. data/eco-helpers.gemspec +1 -1
  5. data/lib/eco/api.rb +2 -0
  6. data/lib/eco/api/common.rb +4 -0
  7. data/lib/eco/api/common/base_loader.rb +54 -0
  8. data/lib/eco/api/common/class_auto_loader.rb +109 -0
  9. data/lib/eco/api/common/class_helpers.rb +33 -0
  10. data/lib/eco/api/common/class_hierarchy.rb +1 -1
  11. data/lib/eco/api/common/class_meta_basics.rb +16 -0
  12. data/lib/eco/api/common/loaders.rb +13 -0
  13. data/lib/eco/api/common/loaders/error_handler.rb +41 -0
  14. data/lib/eco/api/common/loaders/parser.rb +127 -0
  15. data/lib/eco/api/common/loaders/policy.rb +25 -0
  16. data/lib/eco/api/common/loaders/use_case.rb +40 -0
  17. data/lib/eco/api/common/people/default_parsers.rb +3 -12
  18. data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +13 -23
  19. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +20 -35
  20. data/lib/eco/api/common/people/default_parsers/date_parser.rb +15 -26
  21. data/lib/eco/api/common/people/default_parsers/freemium_parser.rb +15 -25
  22. data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +26 -0
  23. data/lib/eco/api/common/people/default_parsers/multi_parser.rb +15 -27
  24. data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +14 -19
  25. data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +24 -35
  26. data/lib/eco/api/common/people/default_parsers/send_invites_parser.rb +15 -25
  27. data/lib/eco/api/common/people/entries.rb +54 -24
  28. data/lib/eco/api/common/people/entry_factory.rb +10 -8
  29. data/lib/eco/api/common/people/person_attribute_parser.rb +29 -12
  30. data/lib/eco/api/common/people/person_entry.rb +308 -216
  31. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +3 -2
  32. data/lib/eco/api/common/people/person_parser.rb +51 -18
  33. data/lib/eco/api/common/session/logger.rb +4 -0
  34. data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +2 -0
  35. data/lib/eco/api/common/version_patches/ecoportal_api/internal_person.rb +1 -1
  36. data/lib/eco/api/common/version_patches/exception.rb +22 -0
  37. data/lib/eco/api/custom.rb +13 -0
  38. data/lib/eco/api/custom/error_handler.rb +20 -0
  39. data/lib/eco/api/custom/namespace.rb +7 -0
  40. data/lib/eco/api/custom/parser.rb +50 -0
  41. data/lib/eco/api/custom/policy.rb +28 -0
  42. data/lib/eco/api/custom/use_case.rb +16 -0
  43. data/lib/eco/api/error.rb +1 -0
  44. data/lib/eco/api/error/handlers.rb +10 -3
  45. data/lib/eco/api/microcases.rb +17 -13
  46. data/lib/eco/api/microcases/account_excluded.rb +24 -0
  47. data/lib/eco/api/microcases/append_usergroups.rb +19 -0
  48. data/lib/eco/api/microcases/core_excluded.rb +4 -4
  49. data/lib/eco/api/microcases/{set_default_group.rb → fix_default_group.rb} +10 -9
  50. data/lib/eco/api/microcases/fix_filter_tags.rb +26 -6
  51. data/lib/eco/api/microcases/people_cache.rb +17 -0
  52. data/lib/eco/api/microcases/people_load.rb +59 -0
  53. data/lib/eco/api/microcases/people_refresh.rb +31 -0
  54. data/lib/eco/api/microcases/people_search.rb +65 -0
  55. data/lib/eco/api/microcases/refresh_abilities.rb +19 -0
  56. data/lib/eco/api/microcases/refresh_default_tag.rb +27 -0
  57. data/lib/eco/api/microcases/s3upload_targets.rb +39 -0
  58. data/lib/eco/api/microcases/set_account.rb +7 -19
  59. data/lib/eco/api/microcases/set_core.rb +5 -5
  60. data/lib/eco/api/microcases/set_core_with_supervisor.rb +23 -0
  61. data/lib/eco/api/microcases/set_supervisor.rb +17 -13
  62. data/lib/eco/api/microcases/strict_search.rb +12 -7
  63. data/lib/eco/api/microcases/with_each.rb +27 -0
  64. data/lib/eco/api/microcases/with_each_leaver.rb +24 -0
  65. data/lib/eco/api/microcases/with_each_present.rb +30 -0
  66. data/lib/eco/api/microcases/with_each_starter.rb +30 -0
  67. data/lib/eco/api/microcases/with_each_subordinate.rb +34 -0
  68. data/lib/eco/api/microcases/with_supervisor.rb +36 -0
  69. data/lib/eco/api/organization/people.rb +72 -35
  70. data/lib/eco/api/organization/presets_factory.rb +13 -4
  71. data/lib/eco/api/policies.rb +11 -7
  72. data/lib/eco/api/session.rb +54 -24
  73. data/lib/eco/api/session/batch.rb +1 -1
  74. data/lib/eco/api/session/batch/base_policy.rb +7 -6
  75. data/lib/eco/api/session/batch/errors.rb +28 -4
  76. data/lib/eco/api/session/batch/feedback.rb +7 -1
  77. data/lib/eco/api/session/batch/job.rb +40 -23
  78. data/lib/eco/api/session/batch/jobs.rb +9 -4
  79. data/lib/eco/api/session/batch/jobs_groups.rb +1 -1
  80. data/lib/eco/api/session/batch/request_stats.rb +91 -58
  81. data/lib/eco/api/session/batch/status.rb +35 -31
  82. data/lib/eco/api/session/config.rb +104 -42
  83. data/lib/eco/api/session/config/api.rb +17 -6
  84. data/lib/eco/api/session/config/logger.rb +2 -2
  85. data/lib/eco/api/session/config/post_launch.rb +1 -1
  86. data/lib/eco/api/session/config/workflow.rb +8 -7
  87. data/lib/eco/api/usecases.rb +47 -33
  88. data/lib/eco/api/usecases/backup/append_usergroups_case.rb +36 -0
  89. data/lib/eco/api/usecases/backup/create_case.rb +104 -0
  90. data/lib/eco/api/usecases/backup/create_details_case.rb +31 -0
  91. data/lib/eco/api/usecases/backup/create_details_with_supervisor_case.rb +48 -0
  92. data/lib/eco/api/usecases/backup/hris_case.rb +124 -0
  93. data/lib/eco/api/usecases/backup/set_default_tag_case.rb +49 -0
  94. data/lib/eco/api/usecases/backup/set_supervisor_case.rb +41 -0
  95. data/lib/eco/api/usecases/backup/transfer_account_case.rb +90 -0
  96. data/lib/eco/api/usecases/backup/update_case.rb +112 -0
  97. data/lib/eco/api/usecases/backup/update_details_case.rb +64 -0
  98. data/lib/eco/api/usecases/backup/upsert_case.rb +114 -0
  99. data/lib/eco/api/usecases/base_case.rb +2 -0
  100. data/lib/eco/api/usecases/base_io.rb +3 -3
  101. data/lib/eco/api/usecases/default_cases.rb +23 -53
  102. data/lib/eco/api/usecases/default_cases/append_usergroups_case.rb +10 -31
  103. data/lib/eco/api/usecases/default_cases/change_email_case.rb +23 -47
  104. data/lib/eco/api/usecases/default_cases/codes_to_tags_case.rb +56 -43
  105. data/lib/eco/api/usecases/default_cases/create_case.rb +15 -101
  106. data/lib/eco/api/usecases/default_cases/create_details_case.rb +11 -26
  107. data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +12 -43
  108. data/lib/eco/api/usecases/default_cases/delete_sync_case.rb +11 -0
  109. data/lib/eco/api/usecases/default_cases/delete_trans_case.rb +14 -0
  110. data/lib/eco/api/usecases/default_cases/email_as_id_case.rb +10 -21
  111. data/lib/eco/api/usecases/default_cases/hris_case.rb +23 -120
  112. data/lib/eco/api/usecases/default_cases/new_email_case.rb +10 -23
  113. data/lib/eco/api/usecases/default_cases/new_id_case.rb +11 -25
  114. data/lib/eco/api/usecases/default_cases/new_id_case0.rb +14 -0
  115. data/lib/eco/api/usecases/default_cases/org_data_convert_case.rb +83 -0
  116. data/lib/eco/api/usecases/default_cases/refresh_abilities_case.rb +30 -0
  117. data/lib/eco/api/usecases/default_cases/refresh_case.rb +7 -20
  118. data/lib/eco/api/usecases/default_cases/reinvite_sync_case.rb +11 -0
  119. data/lib/eco/api/usecases/default_cases/reinvite_trans_case.rb +17 -0
  120. data/lib/eco/api/usecases/default_cases/remove_account_sync_case.rb +11 -0
  121. data/lib/eco/api/usecases/default_cases/remove_account_trans_case.rb +17 -0
  122. data/lib/eco/api/usecases/default_cases/reset_landing_page_case.rb +9 -19
  123. data/lib/eco/api/usecases/default_cases/restore_db_case.rb +92 -0
  124. data/lib/eco/api/usecases/default_cases/set_default_tag_case.rb +32 -40
  125. data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +15 -33
  126. data/lib/eco/api/usecases/default_cases/switch_supervisor_case.rb +66 -57
  127. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +36 -44
  128. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +40 -55
  129. data/lib/eco/api/usecases/default_cases/transfer_account_case.rb +264 -84
  130. data/lib/eco/api/usecases/default_cases/update_case.rb +15 -109
  131. data/lib/eco/api/usecases/default_cases/update_details_case.rb +14 -61
  132. data/lib/eco/api/usecases/default_cases/upsert_case.rb +16 -111
  133. data/lib/eco/api/usecases/use_case_io.rb +9 -9
  134. data/lib/eco/cli/config.rb +10 -2
  135. data/lib/eco/cli/config/default.rb +2 -1
  136. data/lib/eco/cli/config/default/input_filters.rb +58 -0
  137. data/lib/eco/cli/config/default/options.rb +60 -25
  138. data/lib/eco/cli/config/default/people.rb +4 -4
  139. data/lib/eco/cli/config/default/people_filters.rb +108 -0
  140. data/lib/eco/cli/config/default/usecases.rb +69 -32
  141. data/lib/eco/cli/config/default/workflow.rb +37 -27
  142. data/lib/eco/cli/config/filters.rb +50 -0
  143. data/lib/eco/cli/config/filters/input_filters.rb +29 -0
  144. data/lib/eco/cli/config/filters/people_filters.rb +29 -0
  145. data/lib/eco/cli/config/help.rb +49 -0
  146. data/lib/eco/cli/config/options_set.rb +17 -1
  147. data/lib/eco/cli/config/use_cases.rb +79 -53
  148. data/lib/eco/cli/scripting.rb +10 -2
  149. data/lib/eco/cli/scripting/args_helpers.rb +25 -15
  150. data/lib/eco/cli/scripting/argument.rb +1 -0
  151. data/lib/eco/cli/scripting/arguments.rb +1 -1
  152. data/lib/eco/csv/table.rb +1 -1
  153. data/lib/eco/data/crypto/encryption.rb +3 -0
  154. data/lib/eco/language/match.rb +19 -9
  155. data/lib/eco/language/match_modifier.rb +13 -5
  156. data/lib/eco/language/models/collection.rb +77 -56
  157. data/lib/eco/language/models/parser_serializer.rb +39 -15
  158. data/lib/eco/version.rb +1 -1
  159. metadata +63 -18
  160. data/lib/eco/api/microcases/set_default_tag.rb +0 -23
  161. data/lib/eco/api/session/task.rb +0 -175
  162. data/lib/eco/api/usecases/default_case.rb +0 -19
  163. data/lib/eco/api/usecases/default_cases/delete_case.rb +0 -32
  164. data/lib/eco/api/usecases/default_cases/recover_db_case.rb +0 -99
  165. data/lib/eco/api/usecases/default_cases/refresh_presets_case.rb +0 -26
  166. data/lib/eco/api/usecases/default_cases/reinvite_case.rb +0 -41
  167. data/lib/eco/api/usecases/default_cases/remove_account_case.rb +0 -38
  168. data/lib/eco/api/usecases/microed_cases/hris_case.rb +0 -53
  169. data/lib/eco/api/usecases/microed_cases/update_case.rb +0 -33
  170. data/lib/eco/api/usecases/microed_cases/update_details_case.rb +0 -30
  171. data/lib/eco/api/usecases/microed_cases/upsert_case.rb +0 -36
  172. data/lib/eco/cli/config/default/filters.rb +0 -70
  173. data/lib/eco/cli/config/people_filters.rb +0 -38
@@ -31,6 +31,7 @@ module Eco
31
31
  def with_param?
32
32
  @with_param
33
33
  end
34
+
34
35
  end
35
36
  end
36
37
  end
@@ -11,7 +11,7 @@ module Eco
11
11
  @known = {}
12
12
  end
13
13
 
14
- def each(params: {}, &block)
14
+ def each(&block)
15
15
  return to_enum(:each) unless block
16
16
  @known.values.each(&block)
17
17
  end
@@ -3,7 +3,7 @@ module Eco
3
3
  class CSV
4
4
  class Table < ::CSV::Table
5
5
 
6
- # @param ary_arrays [Array<Row>, Array<Array>, Eco::CSV::Table, ::CSV::Table]
6
+ # @param input [Array<Row>, Array<Array>, Eco::CSV::Table, ::CSV::Table]
7
7
  # - when `Array<Array>` => all `rows` as arrays where first array is the **header**
8
8
  def initialize(input)
9
9
  super(to_rows_array(input))
@@ -7,6 +7,7 @@ require_relative '../../cli/scripting'
7
7
 
8
8
  # see some ramblings here: http://distributed-frostbite.blogspot.com/2010/06/file-encryption-in-ruby-with-openssl.html
9
9
 
10
+
10
11
  def run! # this will run only if called from command line (not when require'd nor load'd)
11
12
  include Eco::CLI::Scripting
12
13
  include Eco::Data::Crypto
@@ -145,6 +146,8 @@ module Eco
145
146
  str_c += cipher.final
146
147
  return str_c
147
148
  #EncryptedData.new({content: str_c, key: key, iv: iv})
149
+
150
+
148
151
  end
149
152
  def aes256_decrypt(data, key: , iv: , block_octets: BLOCK_OCTETS)
150
153
  block_bits = block_bits * 8
@@ -1,30 +1,40 @@
1
1
  module Eco
2
2
  module Language
3
- def match?(value, at, mode = MatchModifier.new)
4
- out_match = ->(v) { match?(v, at, mode) }
5
- in_match = ->(a) { match?(value, a, mode) }
3
+
4
+ def match?(value, at, mode = MatchModifier.new, depth: 0)
5
+ out_match = ->(v) { match?(v, at, mode, depth: depth + 1) }
6
+ in_match = ->(a) { match?(value, a, mode, depth: depth + 1) }
7
+ indent_msg = ->(m) { puts (" " * depth) + m if mode.debug? }
6
8
 
7
9
  case
8
10
  when mode.reverse?
9
- return match?(at , value, mode.new.reset_reverse)
11
+ indent_msg.call("reverse value #{value} <--> at: #{at}")
12
+ match?(at , value, mode.new.reset_reverse, depth: depth + 1)
10
13
  when mode.pattern?
14
+ indent_msg.call("at to pattern: #{at}")
11
15
  at = mode.to_regex(at)
12
- return match?(value, at, mode.new.reset_pattern)
16
+ match?(value, at, mode.new.reset_pattern, depth: depth + 1)
13
17
  when value.is_a?(Array)
18
+ indent_msg.call("array #{value} value.#{mode.any?? "any?" : "all?"} match(v_item, at) at: #{at}")
14
19
  return value.any?(&out_match) if mode.any?
15
- return value.all?(&out_match) # defaults to EVERY
20
+ value.all?(&out_match) # defaults to EVERY
16
21
  when at.is_a?(Array)
22
+ indent_msg.call("array #{at} at.#{mode.and?? "all?" : "any?"} match(value, at_item). value: #{value}")
17
23
  return at.all?(&in_match) if mode.and?
18
- return at.any?(&in_match) # defaullts to OR
24
+ at.any?(&in_match) # defaullts to OR
19
25
  when at.is_a?(Regexp)
20
- return at.match?(value)
26
+ indent_msg.call("(#{at.inspect}) at.match?(value); value: #{value}")
27
+ at.match?(value)
21
28
  when value.is_a?(Regexp)
22
- return value.match?(at)
29
+ indent_msg.call("(#{value.inspect}) value.match?(at); at: #{at}")
30
+ value.match?(at)
23
31
  else # final compare
32
+ indent_msg.call("-- final -- mode: #{mode.to_a}; value: #{value}; at: #{at}")
24
33
  m = (value == at) ||
25
34
  (mode.insensitive? && at&.downcase == value&.downcase)
26
35
  (mode.not?) ? !m : m
27
36
  end
28
37
  end
38
+
29
39
  end
30
40
  end
@@ -60,6 +60,10 @@ module Eco
60
60
  self < self.mode - (NOT_MODE | YES_MODE)
61
61
  end
62
62
 
63
+ def debug
64
+ self.push(:debug)
65
+ end
66
+
63
67
  def pattern
64
68
  self.push(:pattern)
65
69
  end
@@ -116,24 +120,28 @@ module Eco
116
120
  self.push(:not)
117
121
  end
118
122
 
123
+ def debug?
124
+ mode.any? {|m| m == :debug}
125
+ end
126
+
119
127
  def pattern?
120
- mode.any? { |m| PATTERN_MODE.include?(m) }
128
+ mode.any? {|m| PATTERN_MODE.include?(m)}
121
129
  end
122
130
 
123
131
  def value?
124
- mode.any? { |m| VALUE_MODE.include?(m) }
132
+ mode.any? {|m| VALUE_MODE.include?(m)}
125
133
  end
126
134
 
127
135
  def reverse?
128
- mode.any? { |m| REVERSE_MODE.include?(m) }
136
+ mode.any? {|m| REVERSE_MODE.include?(m)}
129
137
  end
130
138
 
131
139
  def non_reverse?
132
- mode.any? { |m| NON_REVERSE_MODE.include?(m) }
140
+ mode.any? {|m| NON_REVERSE_MODE.include?(m)}
133
141
  end
134
142
 
135
143
  def any?
136
- mode.any? { |m| ANY_MODE.include?(m) }
144
+ mode.any? {|m| ANY_MODE.include?(m)}
137
145
  end
138
146
 
139
147
  def some?
@@ -4,19 +4,19 @@ module Eco
4
4
  class Collection
5
5
  include Enumerable
6
6
 
7
- ATTR_PRESENCE_METHODS = ["present", "empty", "present_all?", "present_some?"]
8
- ATTR_COLLECTION_METHODS = ["exclude", "remove", "attr", "attr?", "attrs", "unique_attrs", "contains"] + ATTR_PRESENCE_METHODS
7
+ BASIC_METHODS = ["present", "empty", "present_all?", "present_some?"]
8
+ EXTENDED_METHODS = BASIC_METHODS + ["exclude", "remove", "attr", "attr?", "attrs", "unique_attrs", "contains"]
9
9
 
10
10
  class << self
11
11
 
12
- def attr_collection (*attrs)
12
+ def attr_presence(*attrs)
13
13
  block = ->(method) { attrs_create_method(attrs, method) }
14
- ATTR_COLLECTION_METHODS.each(&block)
14
+ BASIC_METHODS.each(&block)
15
15
  end
16
16
 
17
- def attr_presence (*attrs)
17
+ def attr_collection(*attrs)
18
18
  block = ->(method) { attrs_create_method(attrs, method) }
19
- ATTR_PRESENCE_METHODS.each(&block)
19
+ EXTENDED_METHODS.each(&block)
20
20
  end
21
21
 
22
22
  def attrs_create_method(attrs, method)
@@ -35,8 +35,6 @@ module Eco
35
35
 
36
36
  end
37
37
 
38
- #attr_reader :items
39
-
40
38
  def initialize(data = [], klass:, factory: nil, handy: Eco::Assets::Language.new)
41
39
  raise "Raise klass required, given: #{klass}" if !klass
42
40
  @klass = klass
@@ -45,6 +43,15 @@ module Eco
45
43
  @items = to_klass(data)
46
44
  end
47
45
 
46
+ # @!group pure collection methods
47
+ def to_c
48
+ Collection.new(self, klass: @klass, factory: @factory)
49
+ end
50
+
51
+ def new
52
+ newFrom to_a
53
+ end
54
+
48
55
  def newFrom(data)
49
56
  self.class.new(data, klass: @klass, factory: @factory)
50
57
  end
@@ -54,14 +61,6 @@ module Eco
54
61
  newFrom to_a + data
55
62
  end
56
63
 
57
- def to_c
58
- Collection.new(self, klass: @klass, factory: @factory)
59
- end
60
-
61
- def new
62
- self.class.new(to_a, klass: @klass, factory: @factory)
63
- end
64
-
65
64
  def length
66
65
  count
67
66
  end
@@ -70,7 +69,7 @@ module Eco
70
69
  count == 0
71
70
  end
72
71
 
73
- def each(params: {}, &block)
72
+ def each(&block)
74
73
  return to_enum(:each) unless block
75
74
  @items.each(&block)
76
75
  end
@@ -93,47 +92,57 @@ module Eco
93
92
  def delete!(value)
94
93
  self < @items - into_a(value)
95
94
  end
95
+ # @!endgroup
96
96
 
97
- # attr dependant methods
98
- def exclude(attr, value, modifier = Language::MatchModifier.new)
97
+ # @!group `attr` dependant methods
98
+ def exclude(attr, value, modifier = default_modifier)
99
99
  newFrom @items - self.attr(attr, value, modifier)
100
100
  end
101
101
 
102
- def remove(attr, value, modifier = Language::MatchModifier.new)
102
+ def remove(attr, value, modifier = default_modifier)
103
103
  self < exclude(attr, value, modifier)
104
104
  end
105
105
 
106
- def attr(attr, value = true, modifier = Language::MatchModifier.new)
107
- if !!value == value # boolean?
108
- present(attr, value)
109
- else
110
- return newFrom select { |object|
111
- attr_val = fetch_attr(object, attr)
112
- match?(attr_val, value, modifier)
113
- }
106
+ def attr(attr, value = true, modifier = default_modifier)
107
+ return present(attr, value) if boolean?(value)
108
+ select do |object|
109
+ match?(attr_value(object, attr), value, modifier)
110
+ end.yield_self do |matching|
111
+ newFrom matching
114
112
  end
115
113
  end
116
114
 
117
- def attr?(attr, value = true, modifier = Language::MatchModifier.new)
118
- modifier = modifier.new.reverse
119
- if !!value == value # boolean?
120
- present(attr, value).length == length
121
- else
122
- obj_vals = attrs(attr)
123
- return match?(obj_vals, value, modifier)
124
- end
115
+ def attr?(attr, value = true, modifier = default_modifier)
116
+ return present(attr, value).length == length if boolean?(value)
117
+ match?(attrs(attr), value, modifier.new.reverse)
118
+ end
119
+
120
+ def contains(attr, value, modifier = default_modifier)
121
+ self.attr(attr, value, modifier.new.pattern)
125
122
  end
126
123
 
127
124
  def attrs(attr)
128
- map { |object| fetch_attr(object, attr) }
125
+ map { |object| attr_value(object, attr) }
129
126
  end
130
127
 
131
128
  def unique_attrs(attr)
132
129
  to_h(attr).keys
133
130
  end
134
131
 
132
+ def group_by(attr = nil, &block)
133
+ return to_h(attr) if attr
134
+ to_a.group_by(&block) if block
135
+ end
136
+
137
+ def to_h(attr)
138
+ return {} if !attr
139
+ to_a.group_by { |object| object.method(attr).call }
140
+ end
141
+ # @!endgroup
142
+
143
+ # @!group `attr` presence methods
135
144
  def present(attr, flag = true)
136
- block = ->(o) { !!fetch_attr(o, attr) == !!flag }
145
+ block = ->(o) { attr_value_present?(o, attr) == !!flag }
137
146
  newFrom select(&block)
138
147
  end
139
148
 
@@ -148,21 +157,7 @@ module Eco
148
157
  def present_some?(attr, flag = true)
149
158
  present(attr, flag).length > 0
150
159
  end
151
-
152
- def contains(attr, value, modifier = Language::MatchModifier.new)
153
- modifier = modifier.new.pattern
154
- self.attr(attr, value, modifier)
155
- end
156
-
157
- def group_by(attr = nil, &block)
158
- return to_h(attr) if attr
159
- to_a.group_by(&block) if block
160
- end
161
-
162
- def to_h(attr)
163
- return {} if !attr
164
- to_a.group_by { |object| object.method(attr).call }
165
- end
160
+ # @!endgroup
166
161
 
167
162
  protected
168
163
 
@@ -171,12 +166,34 @@ module Eco
171
166
  end
172
167
 
173
168
  def into_a(value)
174
- value = [].push(value) unless value.is_a?(Enumerable)
169
+ value = [].push(value) if value.is_a?(Hash) || !value.is_a?(Enumerable)
175
170
  value.to_a
176
171
  end
177
172
 
178
173
  private
179
174
 
175
+ def attr_value(obj, attr)
176
+ return nil unless obj && attr
177
+ case
178
+ when obj.is_a?(Hash)
179
+ obj[attr]
180
+ when obj.respond_to?(attr.to_sym)
181
+ obj.send(attr)
182
+ end
183
+ end
184
+
185
+ def attr_value_present?(obj, attr)
186
+ return false unless value = attr_value(obj, attr)
187
+ case
188
+ when value.is_a?(Enumerable)
189
+ value.count > 1
190
+ when value.is_a?(String)
191
+ !value.strip.empty?
192
+ else
193
+ !!value
194
+ end
195
+ end
196
+
180
197
  def match?(*args)
181
198
  @handy.match?(*args)
182
199
  end
@@ -187,8 +204,12 @@ module Eco
187
204
  end
188
205
  end
189
206
 
190
- def fetch_attr(object,attr)
191
- object.method(attr).call
207
+ def default_modifier
208
+ Language::MatchModifier.new
209
+ end
210
+
211
+ def boolean?(value)
212
+ value == !!value
192
213
  end
193
214
 
194
215
  end
@@ -1,29 +1,32 @@
1
1
  module Eco
2
2
  module Language
3
3
  module Models
4
-
4
+ # Basic class to define a parser/serializing framework
5
+ # @attr_reader attr [String, Symbol] the attribute this parser/serializer is linked to.
5
6
  class ParserSerializer
6
-
7
7
  attr_reader :attr
8
8
 
9
9
  # Parser/seralizer.
10
10
  # @param attr [String, Symbol] name of the parsed/serialized.
11
11
  # @param dependencies [Hash] provisioning of _**default dependencies**_ that will be required when calling back to the
12
- # parsing or serializing functions.
12
+ # parsing or serializing functions.
13
13
  def initialize(attr, dependencies: {})
14
- @attr = attr
14
+ @attr = attr
15
15
  @dependencies = dependencies
16
+ @parser = {}
17
+ @serializer = {}
16
18
  end
17
19
 
18
20
  # Defines the _parser_ of the attribute.
19
21
  # @note
20
22
  # 1. the _block_ should expect one or two parameters.
21
23
  # 2. the final dependencies is a merge of _default dependencies_ with `parse` call dependencies.
24
+ # @param category [Symbol] a way to classify multiple parsers by category.
22
25
  # @yield [source_data, dependencies] user defined parser that returns the parsed value.
23
26
  # @yieldparam source_data [Any] source data that will be parsed.
24
27
  # @yieldparam dependencies [Hash] hash with the provisioned dependencies.
25
- def def_parser(&block)
26
- @parser = block
28
+ def def_parser(category = :default, &block)
29
+ @parser[category.to_sym] = block
27
30
  self
28
31
  end
29
32
 
@@ -31,11 +34,12 @@ module Eco
31
34
  # @note
32
35
  # 1. the block should expect one or two parameters.
33
36
  # 2. the final dependencies is a merge of _default dependencies_ with `serialize` call dependencies.
37
+ # @param category [Symbol] a way to classify multiple serializers by category.
34
38
  # @yield [source_data, dependencies] user defined serialiser that returns the serialised value.
35
39
  # @yieldparam source_data [Any] source data that will be serialised.
36
40
  # @yieldparam dependencies [Hash] hash with the provisioned dependencies.
37
- def def_serializer(&block)
38
- @serializer = block
41
+ def def_serializer(category = :default, &block)
42
+ @serializer[category.to_sym] = block
39
43
  self
40
44
  end
41
45
 
@@ -45,9 +49,9 @@ module Eco
45
49
  # @raise [Exception] when there is **no** `parser` defined.
46
50
  # @param source [Any] source data to be parsed.
47
51
  # @param dependencies [Hash] _additional dependencies_ that should be merged to the _default dependencies_.
48
- def parse(source, dependencies: {})
49
- raise "There is no parser for this attribue '#{attr}'" if !@parser
50
- @parser.call(source, @dependencies.merge(dependencies), attr)
52
+ def parse(source, category = :default, dependencies: {})
53
+ raise "There is no parser of type '#{category}' for this attribue '#{attr}'" unless parser_category?(category)
54
+ call_block(source, @dependencies.merge(dependencies), attr, &@parser[category.to_sym])
51
55
  end
52
56
 
53
57
  # Calls the `serializer` of this attribute by passing `object` and resolved dependencies.
@@ -56,13 +60,33 @@ module Eco
56
60
  # @raise [Exception] when there is **no** `serializer` defined.
57
61
  # @param object [Any] source data to be serialized.
58
62
  # @param dependencies [Hash] _additional dependencies_ that should be merged to the _default dependencies_.
59
- def serialize(object, dependencies: {})
60
- raise "There is no serializer for this attribue '#{attr}'" if !@serializer
61
- @serializer.call(object, @dependencies.merge(dependencies), attr)
63
+ def serialize(object, category = :default, dependencies: {})
64
+ raise "There is no serializer of type '#{category}' for this attribue '#{attr}'" unless serializer_category?(category)
65
+ call_block(object, @dependencies.merge(dependencies), attr, &@serializer[category.to_sym])
62
66
  end
63
67
 
64
- end
68
+ # Checks if there's a `parser` defined for `category`
69
+ # @return [Boolean] `true` if the parser is defined, and `false` otherwise
70
+ def parser_category?(category = :default)
71
+ @parser.key?(category.to_sym)
72
+ end
73
+
74
+ # Checks if there's a `serializer` defined for `category`
75
+ # @return [Boolean] `true` if the serializer is defined, and `false` otherwise
76
+ def serializer_category?(category = :default)
77
+ @serializer.key?(category.to_sym)
78
+ end
79
+
80
+ private
65
81
 
82
+ # The methods may expect less parameters from some type of parsers.
83
+ # Here, we ensure they are called with the expected number of parameters.
84
+ def call_block(*args, &block)
85
+ params = block.parameters.zip(args).map(&:last)
86
+ yield(*params)
87
+ end
88
+
89
+ end
66
90
  end
67
91
  end
68
92
  end