eco-helpers 0.6.17 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
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