eco-helpers 0.6.17 → 0.7.1

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +19 -0
  3. data/.yardopts +2 -2
  4. data/Gemfile +6 -0
  5. data/Rakefile +27 -0
  6. data/eco-helpers.gemspec +9 -6
  7. data/lib/eco/api.rb +2 -1
  8. data/lib/eco/api/common/people.rb +1 -1
  9. data/lib/eco/api/common/people/base_parser.rb +31 -1
  10. data/lib/eco/api/common/people/default_parsers.rb +5 -1
  11. data/lib/eco/api/common/people/default_parsers/csv_parser.rb +37 -0
  12. data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +0 -1
  13. data/lib/eco/api/common/people/entries.rb +14 -18
  14. data/lib/eco/api/common/people/entry_factory.rb +97 -9
  15. data/lib/eco/api/common/people/person_entry.rb +147 -206
  16. data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +212 -0
  17. data/lib/eco/api/common/people/person_factory.rb +10 -12
  18. data/lib/eco/api/common/people/person_parser.rb +97 -37
  19. data/lib/eco/api/common/session/base_session.rb +1 -2
  20. data/lib/eco/api/common/session/file_manager.rb +1 -1
  21. data/lib/eco/api/organization.rb +2 -1
  22. data/lib/eco/api/organization/people.rb +54 -22
  23. data/lib/eco/api/organization/person_schemas.rb +54 -0
  24. data/lib/eco/api/organization/policy_groups.rb +5 -9
  25. data/lib/eco/api/organization/{presets.rb → presets_factory.rb} +1 -1
  26. data/lib/eco/api/policies.rb +10 -0
  27. data/lib/eco/api/policies/base_policy.rb +14 -0
  28. data/lib/eco/api/policies/policy.rb +20 -0
  29. data/lib/eco/api/policies/used_policies.rb +37 -0
  30. data/lib/eco/api/session.rb +36 -34
  31. data/lib/eco/api/session/batch.rb +94 -44
  32. data/lib/eco/api/session/batch_job.rb +108 -48
  33. data/lib/eco/api/session/batch_jobs.rb +4 -5
  34. data/lib/eco/api/session/batch_status.rb +70 -11
  35. data/lib/eco/api/session/config.rb +22 -5
  36. data/lib/eco/api/session/config/files.rb +10 -1
  37. data/lib/eco/api/session/config/people.rb +18 -5
  38. data/lib/eco/api/session/config/policies.rb +29 -0
  39. data/lib/eco/api/session/config/use_cases.rb +3 -7
  40. data/lib/eco/api/session/job_groups.rb +9 -10
  41. data/lib/eco/api/usecases.rb +2 -1
  42. data/lib/eco/api/usecases/base_case.rb +7 -2
  43. data/lib/eco/api/usecases/default_cases/change_email_case.rb +4 -2
  44. data/lib/eco/api/usecases/default_cases/create_case.rb +2 -1
  45. data/lib/eco/api/usecases/default_cases/create_details_case.rb +3 -1
  46. data/lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb +4 -2
  47. data/lib/eco/api/usecases/default_cases/hris_case.rb +20 -13
  48. data/lib/eco/api/usecases/default_cases/new_email_case.rb +3 -1
  49. data/lib/eco/api/usecases/default_cases/new_id_case.rb +4 -2
  50. data/lib/eco/api/usecases/default_cases/recover_db_case.rb +9 -5
  51. data/lib/eco/api/usecases/default_cases/remove_account_case.rb +4 -2
  52. data/lib/eco/api/usecases/default_cases/set_supervisor_case.rb +4 -2
  53. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +2 -2
  54. data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +2 -2
  55. data/lib/eco/api/usecases/default_cases/update_case.rb +16 -2
  56. data/lib/eco/api/usecases/default_cases/update_details_case.rb +3 -1
  57. data/lib/eco/api/usecases/default_cases/upsert_case.rb +25 -3
  58. data/lib/eco/api/usecases/use_case.rb +23 -140
  59. data/lib/eco/api/usecases/use_case_chain.rb +95 -0
  60. data/lib/eco/api/usecases/use_case_io.rb +117 -0
  61. data/lib/eco/api/usecases/use_group.rb +25 -5
  62. data/lib/eco/common/base_cli_backup.rb +1 -0
  63. data/lib/eco/language/models.rb +1 -1
  64. data/lib/eco/language/models/collection.rb +42 -31
  65. data/lib/eco/language/models/parser_serializer.rb +68 -0
  66. data/lib/eco/version.rb +1 -1
  67. metadata +93 -38
  68. data/lib/eco/api/common/people/types.rb +0 -47
  69. data/lib/eco/api/usecases/case_data.rb +0 -13
  70. data/lib/eco/language/models/attribute_parser.rb +0 -38
  71. data/lib/eco/lexic/dictionary.rb +0 -33
  72. data/lib/eco/lexic/dictionary/dictionary.txt +0 -355484
  73. data/lib/eco/lexic/dictionary/tags.json +0 -38
@@ -0,0 +1,212 @@
1
+ module Eco
2
+ module API
3
+ module Common
4
+ module People
5
+
6
+ # @attr_reader core_attrs [Array<String>] core attributes that are present in the person entry.
7
+ # @attr_reader details_attrs [Array<String>] schema details attributes that are present in the person entry.
8
+ # @attr_reader account_attrs [Array<String>] account attributes that are present in the person entry.
9
+ # @attr_reader all_attrs [Array<String>] all the attrs that are present in the person entry.
10
+ # @attr_reader internal_attrs [Array<String>] all the internally named attributes that the person entry has.
11
+ # @attr_reader aliased_attrs [Array<String>] only those internal attributes present in the person entry that have an internal/external name mapping.
12
+ # @attr_reader direct_attrs [Array<String>] only those internal attributes present in the person entry that do **not** have an internal/external name mapping.
13
+ class PersonEntryAttributeMapper
14
+ @@cached_warnings = {}
15
+
16
+ attr_reader :core_attrs, :details_attrs, :account_attrs, :all_attrs
17
+ attr_reader :internal_attrs, :aliased_attrs, :direct_attrs
18
+
19
+ # Helper class tied to `PersonEntry` that allows to track which attributes of a person entry are present
20
+ # and how they should be mapped between internal and external names if applicable.
21
+ # This class is meant to help in providing a common interface to access entries of source data that come in different formats.
22
+ # @note
23
+ # - if `data` is a `Person` object, its behaviour is `serialise`.
24
+ # - if `data` is **not** a `Person` object, it does a `parse`.
25
+ # - currently **in rework**, so there may be subtle differences that make it temporarily unstable (yet it is reliable).
26
+ # @param data [Hash, Person] `Person` object to be serialized or hashed entry (`CSV::Row` is accepted).
27
+ # @param person_parser [Common::People::PersonParser] parser/serializer of person attributes (it contains a set of attribute parsers).
28
+ # @param attr_map [Eco::Data::Mapper] mapper to translate attribute names from _external_ to _internal_ names and _vice versa_.
29
+ # @param logger [Common::Session::Logger, ::Logger] object to manage logs.
30
+ def initialize(data, person_parser:, attr_map:, logger: ::Logger.new(IO::NULL))
31
+ raise "Constructor needs a PersonParser. Given: #{parser}" if !person_parser.is_a?(Eco::API::Common::People::PersonParser)
32
+ raise "Expecting Mapper object. Given: #{attr_map}" if attr_map && !attr_map.is_a?(Eco::Data::Mapper)
33
+
34
+ @source = data
35
+ @person_parser = person_parser
36
+ @attr_map = attr_map
37
+ @logger = logger
38
+
39
+ if parsing?
40
+ @external_entry = data
41
+ init_attr_trackers
42
+ else # SERIALIZING
43
+ @person = data
44
+ @internal_attrs = @person_parser.all_attrs
45
+ end
46
+
47
+ @core_attrs = @person_parser.target_attrs_core(@internal_attrs)
48
+ @details_attrs = @person_parser.target_attrs_details(@internal_attrs)
49
+ @account_attrs = @person_parser.target_attrs_account(@internal_attrs)
50
+ @all_attrs = @core_attrs | @account_attrs | @details_attrs
51
+ end
52
+
53
+ # To know if currently the object is in parse or serialize mode.
54
+ # @return [Boolean] returns `true` if we are **parsing**, `false` otherwise.
55
+ def parsing?
56
+ !@source.is_a?(Ecoportal::API::Internal::Person)
57
+ end
58
+
59
+ # To know if currently the object is in parse or serialize mode.
60
+ # @return [Boolean] returns `true` if we are **serializing**, `false` otherwise.
61
+ def serializing?
62
+ !parsing?
63
+ end
64
+
65
+ # If there **no** `mapper` defined for the object, it mirrors `value`.
66
+ # If there is a `mapper` defined for the object:
67
+ # 1. if the `value` exists as external, translates it into an internal one.
68
+ # 2. if it doesn't exist, returns `nil`.
69
+ # @note
70
+ # 1. the **scope of attributes** is based on all the attributes recognized by the person parser.
71
+ # 2. the attributes recognized by the person parser are those of of the `Person` model (where details attributes depend on the `schema`).
72
+ # @param value [String, Array<String>] value(s) to be translated into internal names.
73
+ # @return [String, nil, Array<String] the internal name(s) of `value`.
74
+ def to_internal(value)
75
+ return value if !@attr_map
76
+ attr = value
77
+ case value
78
+ when Array
79
+ return value.map do |v|
80
+ to_internal(v)
81
+ end.compact
82
+ when String
83
+ case
84
+ when @attr_map.external?(value)
85
+ attr = @attr_map.to_internal(value)
86
+ when @attr_map.external?(value.strip)
87
+ unless cached_warning("external", "spaces", value)
88
+ logger.warn("The external person field name '#{value}' contains additional spaces in the reference file")
89
+ end
90
+ attr = @attr_map.to_internal(value.strip)
91
+ when @attr_map.internal?(value) || @attr_map.internal?(value.strip) || @attr_map.internal?(value.strip.downcase)
92
+ unless cached_warning("external", "reversed", value)
93
+ logger.warn("The mapper [external, internal] attribute names may be declared reversedly for EXTERNAL attribute: '#{value}'")
94
+ end
95
+ end
96
+ end
97
+
98
+ return nil unless @person_parser.all_attrs.include?(attr)
99
+ end
100
+
101
+ # Serializing helper also used to do a reverse mapping when parsing:
102
+ # - as there could be _internal attributes_ that shared _external attributes_,
103
+ # - when parsing, you use this helper to recognize the source _external attribute_ of each _internal_ one.
104
+ # If there **no** `mapper` defined for the object, it mirrors `value`.
105
+ # If there is a `mapper` defined for the object:
106
+ # 1. if the `value` exists as _internal-, translates it into an _external_ one.
107
+ # 2. if it doesn't exist, returns `nil`.
108
+ # @note
109
+ # 1. the **scope of attributes** is based on all the attributes defined in the current entry.
110
+ # 2. the attributes recognized by the person parser are those of of the `Person` model (where details attributes depend on the `schema`).
111
+ # @param value [String, Array<String>] value(s) to be translated or aliased into external ones.
112
+ # @return [String, nil, Array<String] the external name(s) of `value`.
113
+ def to_external(value)
114
+ return value if !@attr_map
115
+ attr = value
116
+ case value
117
+ when Array
118
+ return value.map do |v|
119
+ to_external(v)
120
+ end.compact
121
+ when String
122
+ case
123
+ when @attr_map.internal?(value)
124
+ attr = @attr_map.to_external(value)
125
+ when @attr_map.internal?(value.strip)
126
+ unless cached_warning("internal", "spaces", value)
127
+ logger.warn("The internal person field name '#{value}' contains additional spaces in the reference file")
128
+ end
129
+ attr = @attr_map.to_external(value.strip)
130
+ when @attr_map.external?(value) || @attr_map.external?(value.strip) || @attr_map.external?(value.strip.downcase)
131
+ unless cached_warning("internal", "reversed", value)
132
+ logger.warn("The mapper [external, internal] attribute names may be declared reversedly for INTERNAL attribute: '#{value}'")
133
+ end
134
+ end
135
+ end
136
+
137
+ return nil unless !@external_entry || attributes(@external_entry).include?(attr)
138
+ attr
139
+ end
140
+
141
+ private
142
+
143
+ # when parsing:
144
+ def init_attr_trackers
145
+ # internal <-> external attributes
146
+ int_aliased = @person_parser.all_attrs.select { |attr| to_external(attr) }
147
+ ext_alias = int_aliased.map { |attr| to_external(attr) }
148
+
149
+ # virtual attrs (non native internal attr that require aliasing):
150
+ ext_vi_aliased = attributes(@external_entry).select do |attr|
151
+ !ext_alias.include?(attr) && @attr_map&.external?(attr)
152
+ end
153
+
154
+ # internal name of external attrs that are not native internal attrs
155
+ int_vi_aliased = ext_vi_aliased.map do |attr|
156
+ # to_internal(attr) can't be used here, becauase virtual fields would get filtered out,
157
+ # as they are not recognized by @parser.all_attrs.include?(attr)
158
+ @attr_map.to_internal(attr)
159
+ end.compact
160
+
161
+ @aliased_attrs = int_aliased + int_vi_aliased
162
+
163
+ int_unlinked = @person_parser.undefined_attrs.select { |attr| !to_external(attr) }
164
+ # those with parser or alias:
165
+ int_linked = @person_parser.all_attrs - int_unlinked
166
+
167
+ ext_aliased = ext_alias + ext_vi_aliased
168
+ # those that are direct external to internal:
169
+ ext_direct = attributes(@external_entry) - ext_aliased
170
+ # to avoid collisions between internal names:
171
+ @direct_attrs = ext_direct - int_linked
172
+ @internal_attrs = @aliased_attrs | @direct_attrs
173
+ end
174
+
175
+ def attributes(value)
176
+ case value
177
+ when CSV::Row
178
+ value&.headers
179
+ when Hash
180
+ value&.keys
181
+ when PersonEntry
182
+ @person_parser.target_attrs_core
183
+ else
184
+ []
185
+ end
186
+ end
187
+
188
+ # LOGGER
189
+ def logger
190
+ @logger || ::Logger.new(IO::NULL)
191
+ end
192
+
193
+ def cached_warning(*args)
194
+ unless exists = !!@@cached_warnings.dig(*args)
195
+ args.reduce(@@cached_warnings) do |cache, level|
196
+ cache[level] = {} if !cache.key?(level)
197
+ cache[level]
198
+ end
199
+ end
200
+ exists
201
+ end
202
+
203
+ def fatal(msg)
204
+ logger.fatal(msg)
205
+ exit
206
+ end
207
+
208
+ end
209
+ end
210
+ end
211
+ end
212
+ end
@@ -4,8 +4,6 @@ module Eco
4
4
  module People
5
5
  class PersonFactory
6
6
 
7
- include Common::People
8
-
9
7
  attr_reader :schema_attrs
10
8
 
11
9
  def initialize(person: {}, schema: {}, account: {}, modifier: Common::People::PersonModifier.new)
@@ -43,9 +41,9 @@ module Eco
43
41
 
44
42
  def klass
45
43
  if @modifier.external?
46
- EXTERNAL::Person
44
+ Ecoportal::API::V1::Person
47
45
  else
48
- INTERNAL::Person
46
+ Ecoportal::API::Internal::Person
49
47
  end
50
48
  end
51
49
 
@@ -69,10 +67,10 @@ module Eco
69
67
  end
70
68
 
71
69
  def person_hash(person)
72
- case
73
- when is_person?(person)
70
+ case person
71
+ when Ecoportal::API::V1::Person
74
72
  JSON.parse(person.doc.to_json)
75
- when person.is_a?(Hash)
73
+ when Hash
76
74
  JSON.parse(person.to_json)
77
75
  else
78
76
  {}
@@ -80,12 +78,12 @@ module Eco
80
78
  end
81
79
 
82
80
  def details_hash(details)
83
- case
84
- when details.is_a?(EXTERNAL::PersonDetails)
81
+ case details
82
+ when Ecoportal::API::V1::PersonDetails
85
83
  doc = JSON.parse(details.doc.to_json)
86
- when details.is_a?(EXTERNAL::PersonSchema)
84
+ when Ecoportal::API::V1::PersonSchema
87
85
  doc =JSON.parse(details.doc.to_json)
88
- when details.is_a?(Hash)
86
+ when Hash
89
87
  doc = JSON.parse(details.to_json)
90
88
  doc = doc["details"] if doc.key?("details")
91
89
  else
@@ -97,7 +95,7 @@ module Eco
97
95
 
98
96
  def account_hash(account)
99
97
  case
100
- when account.is_a?(INTERNAL::Account)
98
+ when account.is_a?(Ecoportal::API::Internal::Account)
101
99
  JSON.parse(account.doc.to_json)
102
100
  when account.is_a?(Hash)
103
101
  doc = JSON.parse(account.to_json)
@@ -2,17 +2,35 @@ module Eco
2
2
  module API
3
3
  module Common
4
4
  module People
5
+
6
+ # Class to define/group a set of parsers/serializers.
7
+ #
8
+ # @attr_reader schema [Ecoportal::API::V1::PersonSchema, nil] schema of person details that this parser will be based upon.
9
+ # @attr_reader details_attrs [Array<String>] internal names of schema details attributes.
10
+ # @attr_reader all_attrs [Array<String>] all the internal name attributes, including _core_, _account_ and _details_.
5
11
  class PersonParser
6
12
  CORE_ATTRS = ["id", "external_id", "email", "name", "supervisor_id"]
7
13
  ACCOUNT_ATTRS = ["policy_group_ids", "filter_tags", "default_tag"]
8
14
  TYPE = [:select, :text, :date, :number, :phone_number, :boolean, :multiple]
15
+ FORMAT = [:csv, :xml, :json]
9
16
 
10
17
  attr_reader :schema
11
18
  attr_reader :details_attrs, :all_attrs
12
19
  attr_reader :defined_attrs
13
20
 
14
- def initialize(schema: nil) #), logger: nil)
15
- #self.schema = schema
21
+ # @example Example of usage:
22
+ # person_parser = PersonParser.new(schema: schema)
23
+ # person_parser.define_attribute("example") do |parser|
24
+ # parser.def_parser do |str, deps|
25
+ # i = value.to_i rescue 0
26
+ # i +=5 if deps.dig(:sum_5)
27
+ # i
28
+ # end.def_serializer do |value|
29
+ # value.to_s
30
+ # end
31
+ # end
32
+ # @param schema [Ecoportal::API::V1::PersonSchema, nil] schema of person details that this parser will be based upon.
33
+ def initialize(schema: nil)
16
34
  raise "Constructor needs a PersonSchema. Given: #{schema}" if schema && !schema.is_a?(Ecoportal::API::V1::PersonSchema)
17
35
  @details_attrs = []
18
36
  @parsers = {}
@@ -23,49 +41,66 @@ module Eco
23
41
  end
24
42
 
25
43
  @all_attrs = CORE_ATTRS + ACCOUNT_ATTRS + @details_attrs
26
- #init_default_parsers if @schema
27
44
  end
28
45
 
46
+ # Lists all defined attributes, types and formats.
47
+ # @return [Array<String>] the list of defined parsers/serializers.
48
+ def list_defined
49
+ @parsers.keys
50
+ end
51
+
52
+ # Scopes `source_attrs` using the _**core** attributes_.
53
+ # @note use this helper to know which among your attributes are **core** ones.
54
+ # @param source_attrs [Array<String>]
55
+ # @return [Array<String>] the scoped **core** attributes, if `source_attrs` is not `nil`. All the _core attributes_, otherwise.
29
56
  def target_attrs_core(source_attrs = nil)
30
57
  return CORE_ATTRS if !source_attrs
31
58
  scoped_attrs(source_attrs, CORE_ATTRS)
32
59
  end
33
60
 
61
+ # Scopes `source_attrs` using the schema _**details** attributes_.
62
+ # @note use this helper to know which among your attributes are schema **details** ones.
63
+ # @param source_attrs [Array<String>]
64
+ # @return [Array<String>] the scoped **details** attributes, if `source_attrs` is not `nil`. All the _details attributes_, otherwise.
34
65
  def target_attrs_details(source_attrs = nil)
35
66
  return @details_attrs if ! source_attrs
36
67
  scoped_attrs(source_attrs, @details_attrs)
37
68
  end
38
69
 
70
+ # Scopes `source_attrs` using the schema _**account** attributes_.
71
+ # @note use this helper to know which among your attributes are **account** ones.
72
+ # @param source_attrs [Array<String>]
73
+ # @return [Array<String>] the scoped **account** attributes, if `source_attrs` is not `nil`. All the _account attributes_, otherwise.
39
74
  def target_attrs_account(source_attrs = nil)
40
75
  return ACCOUNT_ATTRS if !source_attrs
41
76
  scoped_attrs(source_attrs, ACCOUNT_ATTRS)
42
77
  end
43
78
 
44
- def defined
45
- @parsers.keys
46
- end
47
-
48
- def list
49
- @parsers.keys
50
- end
51
-
79
+ # Returns a list of all the internal attributes of the model that have a parser defined.
80
+ # @note it excludes any parser that is not in the model, such as type parsers (i.e. ``:boolean`, ``:multiple`)
81
+ # @return [Array<String>] list of all attribute defined parsers.
52
82
  def defined_attrs
83
+ defined = @parsers.keys
53
84
  defined - (defined - all_attrs)
54
85
  end
55
86
 
87
+ # Returns a list of all the internal attributes of the model that do **not** have a parser defined.
88
+ # @note it excludes any parser that is **not** in the model, such as type parsers (i.e. :boolean, :multiple)
89
+ # @return [Array<String>] list of all attributes without a defined parser.
56
90
  def undefined_attrs
57
91
  all_attrs - defined_attrs
58
92
  end
59
93
 
94
+ # @param attr [String] internal name of an attribute.
95
+ # @return [Boolean] `true` if the attribute `attr` has parser defined, and `false` otherwise.
60
96
  def defined?(attr)
61
- !!@parsers[attr]
97
+ @parsers.key?(attr)
62
98
  end
63
99
 
64
- #def append(attr, dependencies: {}, &bloc)
65
- # @parsers[attr] = into_a(parsers[attr]).push(define_parser(attr, dependencies, &bloc))
66
- #end
67
-
68
- # merges parser overriding self for exisint parsers
100
+ # Helper to **merge** a set of parsers of another `PersonParser` into the current object.
101
+ # @note if there are parsers with same name, it **overrides** the ones of the current object with them.
102
+ # @param parser [Eco::API::Common::People::PersonParser] a `PersonParser` containing defined parsers.
103
+ # @return [Eco::API::Common::People::PersonParser] the current object (to ease chainig).
69
104
  def merge(parser)
70
105
  return self if !parser
71
106
  raise "Expected a PersonParser object. Given #{parser}" if !parser.is_a?(PersonParser)
@@ -73,16 +108,51 @@ module Eco
73
108
  self
74
109
  end
75
110
 
76
- def define_attribute(attr, dependencies: {}, &bloc)
77
- @parsers[attr] = define_parser(attr, dependencies, &bloc)
111
+
112
+ # Helper to define and associate a parser/serializer to a type or attribute.
113
+ # @raise [Exception] if trying to define a parser/serializer for:
114
+ # - an unkown attribute (`String`)
115
+ # - an unrecognized type or format (`Symbol`)
116
+ # @param attr [String] type (`Symbol`) or attribute (`String`) to define the parser/serializer to.
117
+ # @param dependencies [Hash] dependencies to be used when calling the parser/serializer.
118
+ # @yield [parser] the definition of the parser.
119
+ # @yieldparam parser [Eco::Language::Models::ParserSerializer] parser to define.
120
+ # @return [Eco::API::Common::People::PersonParser] the current object (to ease chainig).
121
+ def define_attribute(attr, dependencies: {}, &definition)
122
+ if !valid?(attr)
123
+ msg = "The attribute '#{attr_to_str(attr)}' is not part of core, account or target schema, or does not match any type: #{@details_attrs}"
124
+ raise msg
125
+ end
126
+
127
+ Eco::Language::Models::ParserSerializer.new(attr, dependencies: dependencies).tap do |parser|
128
+ @parsers[attr] = parser
129
+ definition.call(parser)
130
+ end
131
+
78
132
  self
79
133
  end
80
134
 
135
+ # Call to parser `source` value of attribute or type `attr` into an internal valid value.
136
+ # @note dependencies introduced on `parse` call will be merged with those defined during the
137
+ # initialization of the parser `attr`.
138
+ # @raise [Exception] if there is **no** parser for attribute or type `attr`.
139
+ # @param attr [String] target attribute or type to **parse**.
140
+ # @param source [Any] source value to be parsed.
141
+ # @param deps [Hash] key-value pairs of call dependencies.
142
+ # @return [Any] a valid internal value.
81
143
  def parse(attr, source, deps: {})
82
144
  raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr)
83
145
  @parsers[attr].parse(source, dependencies: deps)
84
146
  end
85
147
 
148
+ # Call to serialise `object` value of attribute or type `attr` into an external valid value.
149
+ # @note dependencies introduced on `serialise` call will be merged with those defined during the
150
+ # initialization of the parser/serialiser `attr`.
151
+ # @raise [Exception] if there is **no** serialiser for attribute or type `attr`.
152
+ # @param attr [String] target attribute or type to **serialize**.
153
+ # @param object [Any] object value to be serialized.
154
+ # @param deps [Hash] key-value pairs of call dependencies.
155
+ # @return a valid external value.
86
156
  def serialize(attr, object, deps: {})
87
157
  raise "There is no parser for attribute '#{attr}'" if !self.defined?(attr)
88
158
  @parsers[attr].serialize(object, dependencies: deps)
@@ -90,6 +160,7 @@ module Eco
90
160
 
91
161
  protected
92
162
 
163
+ # @return [Hash] attr-parser pairs with all the defined type and attribute parsers/serializers.
93
164
  def hash
94
165
  @parsers
95
166
  end
@@ -102,35 +173,24 @@ module Eco
102
173
  (source_attrs + parsed_attrs) & (direct_attrs + parsed_attrs)
103
174
  end
104
175
 
105
- def define_parser(attr, dependencies = {}, &definition)
106
- if !valid?(attr)
107
- str_attr = (attr.is_a?(Symbol) ? ":" : "") + attr.to_s
108
- msg = "The attribute '#{str_attr}' is not part of core, account or target schema, or does not match any type: #{@details_attrs}"
109
- raise msg
110
- end
111
- parser = Eco::Language::Models::AttributeParser.new(attr, dependencies: dependencies)
112
- #yield(parser)
113
- definition.call(parser)
114
- parser
176
+ def attr_to_str(attr)
177
+ attr.is_a?(Symbol)? ":#{attr.to_s}" : "#{attr.to_s}"
115
178
  end
116
179
 
117
180
  def valid?(attr)
118
- (attr.is_a?(Symbol) && valid_type?(attr)) ||
119
- (attr.is_a?(String) && (!@schema || valid_attr?(attr)))
181
+ valid_attr?(attr) || valid_type?(attr) || valid_format?(attr)
120
182
  end
121
183
 
122
184
  def valid_attr?(attr)
123
- @all_attrs.include?(attr)
185
+ attr.is_a?(String) && (!@schema || @all_attrs.include?(attr))
124
186
  end
125
187
 
126
188
  def valid_type?(attr)
127
- TYPE.include?(attr)
189
+ attr.is_a?(Symbol) && TYPE.include?(attr)
128
190
  end
129
191
 
130
- def into_a(value)
131
- value = [] if value == nil
132
- value = [].push(value) unless value.is_a?(Array)
133
- value
192
+ def valid_format?(attr)
193
+ attr.is_a?(Symbol) && FORMAT.include?(attr)
134
194
  end
135
195
 
136
196
  end