lib/eco/api/common/people/person_entry.rb in eco-helpers-1.5.1 vs lib/eco/api/common/people/person_entry.rb in eco-helpers-1.5.2
- old
+ new
@@ -7,11 +7,11 @@
# This class is meant to provide a common interface to access entries of source data that come in different formats.
# @note
# - if `data` is a `Person` object, its behaviour is `serialise`.
# - if `data` is **not** a `Person` object, it does a `parse`.
# - currently **in rework**, so there may be subtle differences that make it temporarily unstable (yet it is reliable).
- # @param data [Hash, Person] `Person` object to be serialized or hashed entry (`CSV::Row` is accepted).
+ # @param data [Hash, Ecoportal::API::V1::Person] `Person` object to be serialized or hashed entry (`CSV::Row` is accepted).
# @param person_parser [Common::People::PersonParser] parser/serializer of person attributes (it contains a set of attribute parsers).
# @param attr_map [Eco::Data::Mapper] mapper to translate attribute names from _external_ to _internal_ names and _vice versa_.
# @param dependencies [Hash] hash where _keys_ are internal attribute names. It is mostly used to deliver final dependencies to attribute parsers/serializers.
# @param logger [Common::Session::Logger, ::Logger] object to manage logs.
def initialize(data, person_parser:, attr_map:, dependencies: {}, logger: ::Logger.new(IO::NULL))
@@ -24,21 +24,47 @@
@logger = logger
@attr_map = attr_map
@emap = PersonEntryAttributeMapper.new(@source, person_parser: @person_parser, attr_map: @attr_map, logger: @logger)
if parsing?
- @external_entry = data
- @serialized_entry = _mapped_entry(@external_entry)
- @internal_entry = _internal_entry(@serialized_entry)
+ @external_entry = __external_entry(data)
+ @mapped_entry = __mapped_entry(@external_entry)
+ @internal_entry = __internal_entry(@mapped_entry)
+ @final_entry = __final_entry(@internal_entry)
else # SERIALIZING
@person = data
- @internal_entry = _internal_entry(@person)
- @serialized_entry = _mapped_entry(@internal_entry)
- #@external_entry = external_entry
+ @final_entry = __final_entry(@person)
+ @internal_entry = __internal_entry(@final_entry)
+ @mapped_entry = __mapped_entry(@internal_entry)
+ @external_entry = __external_entry(@mapped_entry)
end
end
+ # Generates a new entry
+ # @return [PersonEntry]
+ def new(data)
+ self.class.new(data, person_parser: @person_parser, attr_map: @attr_map, dependencies: @deps, logger: @logger)
+ end
+
+ # @note completely serialized entry.
+ # @return [Hash] entry `Hash` with **external** attribute names, and values and types thereof.
+ def external_entry
+ @external_entry
+ end
+
+ # @note just one step away from being completely parsed (only types parsing pending).
+ # @return [Hash] entry `Hash` with **internal** attribute names and values, but **external** types.
+ def internal_entry
+ @internal_entry
+ end
+
+ # @note values ready to be set to a person.
+ # @return [Hash] entry `Hash` with **internal** attribute names, values and types.
+ def final_entry
+ @final_entry
+ end
+
# To know if currently the object is in parse or serialize mode.
# @return [Boolean] returns `true` if we are **parsing**, `false` otherwise.
def parsing?
!@source.is_a?(Ecoportal::API::Internal::Person)
end
@@ -47,347 +73,403 @@
# @return [Boolean] returns `true` if we are **serializing**, `false` otherwise.
def serializing?
!parsing?
end
+ # @note `Eco::API::Common::People::EntryFactory#entries` adds this `idx`
+ # @return [Integer] the entry number in the input file
+ def idx
+ final_entry["idx"]
+ end
+
# @return [String, nil] the _internal id_ of this person if defined.
def id
- @internal_entry["id"]
+ final_entry["id"]
end
def id?
- @internal_entry.key?("id")
+ final_entry.key?("id")
end
# @return [String, nil] the _external id_ of this person if defined.
def external_id
- @internal_entry["external_id"]
+ final_entry["external_id"]
end
def external_id?
- @internal_entry.key?("external_id")
+ final_entry.key?("external_id")
end
# @return [String, nil] the _name_ of this person if defined.
def name
- @internal_entry["name"]
+ final_entry["name"]
end
def name?
- @internal_entry.key?("name")
+ final_entry.key?("name")
end
# @return [String, nil] the _email_ of this person if defined.
def email
- @internal_entry["email"]
+ final_entry["email"]
end
def email?
- @internal_entry.key?("email")
+ final_entry.key?("email")
end
# @return [String, nil] the _supervisor id_ of this person if defined.
def supervisor_id
- @internal_entry["supervisor_id"]
+ final_entry["supervisor_id"]
end
def supervisor_id=(value)
- @internal_entry["supervisor_id"] = value
+ final_entry["supervisor_id"] = value
end
def supervisor_id?
- @internal_entry.key?("supervisor_id")
+ final_entry.key?("supervisor_id")
end
def filter_tags
- @internal_entry["filter_tags"]
+ final_entry["filter_tags"] || []
end
def filter_tags?
- @internal_entry.key?("filter_tags")
+ final_entry.key?("filter_tags")
end
+ def policy_group_ids
+ final_entry["policy_group_ids"] || []
+ end
+
def policy_group_ids?
- @internal_entry.key?("policy_group_ids")
+ final_entry.key?("policy_group_ids")
end
def default_tag?
- @internal_entry.key?("default_tag")
+ final_entry.key?("default_tag")
end
def default_tag
- @internal_entry["default_tag"]
+ final_entry["default_tag"]
end
# Provides a reference of this person.
# @return [String] string summary of this person identity.
def to_s(options)
options = into_a(options)
case
when options.include?(:identify)
- "'#{name}' ('#{external_id}': '#{email}')"
+ str_id = id ? "id: '#{id}'; " : ""
+ "(row: #{idx}) '#{name}' (#{str_id}ext_id: '#{external_id}'; email: '#{email}')"
else
- @internal_entry.each.map do |k, v|
+ final_entry.each.map do |k, v|
"'#{k}': '#{v.to_json}'"
end.join(" | ")
end
end
# Setter to fill in all the `core` properties of the `Person` that are present in the `Entry`.
# @note it only sets those core properties defined in the entry.
# Meaning that if an core property is not present in the entry, this will not be set on the target person.
- # @param person [Person] the person we want to set the core values to.
+ # @param person [Ecoportal::API::V1::Person] the person we want to set the core values to.
# @param exclude [String, Array<String>] core attributes that should not be set/changed to the person.
def set_core(person, exclude: nil)
scoped_attrs = @emap.core_attrs - into_a(exclude)
- @internal_entry.slice(*scoped_attrs).each do |attr, value|
- _set_to_core(person, attr, value)
+ @final_entry.slice(*scoped_attrs).each do |attr, value|
+ set_part(person, attr, value)
end
end
- # Setter to fill in all the schema `details` fields of the `Person` that are present in the `Entry`.
- # @note it only sets those details properties defined in the entry.
- # Meaning that if an details property is not present in the entry, this will not be set on the target person.
- # @param person [Person] the person we want to set the schema fields' values to.
- # @param exclude [String, Array<String>] schema field attributes that should not be set/changed to the person.
- def set_details(person, exclude: nil)
- person.add_details(@person_parser.schema) if !person.details || !person.details.schema_id
- scoped_attrs = @emap.details_attrs - into_a(exclude)
- @internal_entry.slice(*scoped_attrs).each do |attr, value|
- _set_to_details(person, attr, value)
- end
- end
-
# Setter to fill in the `account` properties of the `Person` that are present in the `Entry`.
# @note it only sets those account properties defined in the entry.
# Meaning that if an account property is not present in the entry, this will not be set on the target person.
- # @param person [Person] the person we want to set the account values to.
+ # @param person [Ecoportal::API::Internal::Person] the person we want to set the account values to.
# @param exclude [String, Array<String>] account properties that should not be set/changed to the person.
def set_account(person, exclude: nil)
person.account = {} if !person.account
person.account.permissions_preset = nil unless person.account.permissions_preset = "custom"
scoped_attrs = @emap.account_attrs - into_a(exclude)
- @internal_entry.slice(*scoped_attrs).each do |attr, value|
- _set_to_account(person, attr, value)
+ @final_entry.slice(*scoped_attrs).each do |attr, value|
+ set_part(person.account, attr, value)
end
end
- # Entry represented in a `Hash` with **external** attribute names and values thereof.
- # @note normally used to obtain a **serialized entry**.
- # @return [Hash] with **external** names and values.
- def to_hash
- external_entry
+ # Setter to fill in all the schema `details` fields of the `Person` that are present in the `Entry`.
+ # @note it only sets those details properties defined in the entry.
+ # Meaning that if an details property is not present in the entry, this will not be set on the target person.
+ # @param person [Ecoportal::API::V1::Person] the person we want to set the schema fields' values to.
+ # @param exclude [String, Array<String>] schema field attributes that should not be set/changed to the person.
+ def set_details(person, exclude: nil)
+ person.add_details(@person_parser.schema) if !person.details || !person.details.schema_id
+ scoped_attrs = @emap.details_attrs - into_a(exclude)
+ @final_entry.slice(*scoped_attrs).each do |attr, value|
+ set_part(person.details, attr, value)
+ end
end
- # Entry represented in a `Hash` with **external** attribute names and values thereof.
- # @note normally used to obtain a **serialized entry**.
- # @return [Hash] with **external** names and values.
- def external_entry
- @emap.all_attrs.each_with_object({}) do |attr, hash|
- unless hash.key?(ext_attr = @emap.to_external(attr))
- hash[ext_attr] = @serialized_entry[attr]
- end
- end
+ private
+
+ # @return [Hash] entry in raw: that with **external** names, values and types.
+ def __external_entry(data)
+ return data if parsing?
+ _external_serializing(data)
end
- def internal_entry
- @internal_entry
+ # @return [Hash] that with **internal** names but **external** values and types.
+ def __mapped_entry(data)
+ return _mapped_parsing(data) if parsing?
+ _mapped_serializing(data)
end
- def doc
- return @person.doc if instance_variable_defined?(:@person) && @person
+ # @return [Hash] that with **internal** names and values, but **external** values and types.
+ def __internal_entry(data)
+ return _internal_parsing(data) if parsing?
+ _internal_serializing(data)
+ end
- core_attrs = @emap.core_attrs
- details_attrs = @emap.details_attrs
- account_attrs = @emap.account_attrs
+ # @return [Hash] that with **internal** names, values and types.
+ def __final_entry(data)
+ return _final_parsing(data) if parsing?
+ _final_serializing(data)
+ end
- internal_entry.slice(*core_attrs).tap do |core_hash|
- unless details_attrs.empty?
- schema_id = @person_parser.schema.id
- details_fields = @person_parser.schema.doc["fields"].each_with_object([]) do |fld, flds|
- if details_attrs.include?(fld.alt_id)
- flds << fld.merge("value" => internal_entry[fld.alt_id]).slice("id", "alt_id", "type", "name", "shared", "multiple", "value")
- end
- end
- core_hash.merge!({
- "details" => {
- "schema_id" => schema_id,
- "fields" => details_fields
- }
- })
+ # Serializing helper that maps internal attributes to external attribute names
+ # @note **Serialize**: here we unaliase internal attribute names into external ones.
+ # @param mapped_entry [Hash] that with **internal** names but **external** values and types.
+ # @return [Hash] with **external** names, values and types.
+ def _external_serializing(mapped_entry)
+ target_attrs = @emap.all_attrs | @emap.aliased_attrs
+ rest_keys = mapped_entry.keys - target_attrs
+ target_attrs -= ["send_invites"]
+ external_entry = target_attrs.each_with_object({}) do |attr, hash|
+ unless hash.key?(ext_attr = @emap.to_external(attr))
+ hash[ext_attr] = mapped_entry[attr]
end
-
- unless account_attrs.empty?
- account_hash = internal_entry.slice(*account_attrs)
- core_hash.merge!({
- "account" => account_hash
- })
- end
end
+ merge_missing_attrs(external_entry, mapped_entry.slice(*rest_keys))
end
- private
-
- def _set_to_core(person, attr, value)
- value = value&.downcase if attr == "email"
- multiple = ["filter_tags"].include?(attr)
- if multiple
- value = @person_parser.parse(:multiple, value)
- value = value.map { |v| v&.upcase } if attr == "filter_tags"
- # preserve previous order
- current = into_a(person.send(attr))
- value = (current & value) + (value - current)
- else
- value = value&.strip
+ # Parsing helper that aliases attribute names (from internal to external names)
+ # @note **Parse**: here we aliase external attribute names into internal ones.
+ # @param external_entry [Hash] entry in raw, with **external** names and values.
+ # @return [Hash] entry with **internal** names, but still **external** values and types.
+ def _mapped_parsing(external_entry)
+ mapped_hash = @emap.aliased_attrs.each_with_object({}) do |attr, hash|
+ hash[attr] = external_entry[@emap.to_external(attr)]
end
+ external_entry.slice(*@emap.direct_attrs).merge(mapped_hash)
+ end
- person.send("#{attr}=", value)
+ # Serializing helper that **serializes values** that have a parser/serializer defined.
+ # @note **Serializing**:
+ # 1. here we tranform internal into external **values**.
+ # 2. when running the serializers, it overrides existing keys.
+ # @param internal_entry [Hash] entry with **internal** names and values, but **external** types.
+ # @return [Hash] entry with **internal** names and **external** values and types.
+ def _mapped_serializing(internal_entry)
+ internal_entry.merge(_serialize_values(internal_entry, :internal))
end
- def _set_to_account(person, attr, value)
- return if !person.account
- multiple = ["policy_group_ids", "login_provider_ids"].include?(attr)
- if multiple
- value = @person_parser.parse(:multiple, value)
- # preserve previous order
- current = into_a(person.account.send(attr))
- value = (current & value) + (value - current)
- end
+ # Parsing helper that just **parses the values** that have a parser/serializer defined.
+ # @note this entry will still miss the type parsing (i.e. to `Array` if `multiple`)
+ # @param mapped_entry [Hash] the entry with the _internal attribute_ names but the _external values_.
+ # @return [Hash] the `internal entry` with the **internal** attributes names and values.
+ def _internal_parsing(mapped_entry)
+ mapped_entry.merge(_parse_values(mapped_entry, :internal))
+ end
- person.account.send("#{attr}=", value)
+ # Serializing helper that just creates the _internal entry_ out of a _parsed entry_ (serializes the type).
+ # @param final_entry [Hash] the entry with all _internal_ (attributes, values and types)
+ # @return [Hash] the `internal entry` with the **internal** attributes names and values, but external types.
+ def _internal_serializing(final_entry)
+ final_entry = final_entry.merge(_serialize_values(final_entry, :final))
+ core_account = @person_parser.target_attrs_account + @person_parser.target_attrs_core
+ core_account_hash = core_account.reduce({}) do |hash, attr|
+ hash.merge(hash_attr(attr, _serialize_type(attr, final_entry[attr])))
+ end
+ details_hash = @person_parser.target_attrs_details.reduce({}) do |hash, attr|
+ hash.merge(hash_attr(attr, _serialize_type(attr, final_entry[attr], schema: @person_parser.schema)))
+ end
+ merging(core_account_hash, details_hash) do |internal_entry|
+ merge_missing_attrs(internal_entry, final_entry)
+ end
end
- def _set_to_details(person, attr, value)
- return if !person.details
- unless field = person.details.get_field(attr)
- fatal("Field '#{attr}' does not exist in details of schema: '#{person.details.schema_id}'")
+ # Parsing helper where attributes with custom parsers are already parsed, but
+ # it finishes to parse the types (i.e. to `Array` if `multiple`)
+ # @param internal_entry [Hash] the entry with the **internal** _attribute_ names and values but the **external** types.
+ # @return [Hash] the `parsed entry` with the **internal** final attributes names, values and types.
+ def _final_parsing(internal_entry)
+ core_account = @emap.account_attrs + @emap.core_attrs
+ core_account_hash = internal_entry.slice(*core_account).each_with_object({}) do |(attr, value), hash|
+ hash[attr] = _parse_type(attr, value)
end
- value = nil if value.to_s.empty?
- value = @person_parser.parse(:multiple, value) if field.multiple
- if @person_parser.defined?(field.type.to_sym)
- value = @person_parser.parse(field.type.to_sym, value, deps: {"attr" => attr})
+ details_hash = internal_entry.slice(*@emap.details_attrs).each_with_object({}) do |(attr, value), hash|
+ hash[attr] = _parse_type(attr, value, schema: @person_parser.schema)
end
- person.details[attr] = value
+ merging(core_account_hash, details_hash) do |final_entry|
+ final_entry = merge_missing_attrs(final_entry, internal_entry)
+ final_entry.merge(_parse_values(final_entry, :final))
+ end
end
- def _get_from_core (person, attr)
- person.send(attr)
+ # Serializing helper that just creates the _parsed entry_ out of a `Person` object.
+ # @note
+ # - when unnesting attributes, the overriding precedence for collisions is
+ # - `core` -> _overrides_ -> `account` -> _overrides_ -> `details`
+ # - to keep things consistent, the `internal entry` hash has keys in this order:
+ # - `core`, `account`, `details`.
+ # @param person [Ecoportal::API::V1::Person] the `Person` object to transform into a _parsed entry_.
+ # @return [Hash] the `parsed entry` with the **internal** attributes names and internal typed values.
+ def _final_serializing(person)
+ core_hash = @person_parser.target_attrs_core.reduce({}) do |hash, attr|
+ hash.merge(hash_attr(attr, get_part(person, attr)))
+ end
+ account_hash = @person_parser.target_attrs_account.reduce({}) do |hash, attr|
+ hash.merge(hash_attr(attr, get_part(person.account, attr)))
+ end
+ details_hash = @person_parser.target_attrs_details.reduce({}) do |hash, attr|
+ hash.merge(hash_attr(attr, get_part(person.details, attr)))
+ end
+ merging(core_hash, account_hash, details_hash) do |final_entry|
+ final_entry["Has account?"] = !!person.account
+ final_entry.merge(_serialize_values(person, :person))
+ end
end
- def _get_from_account (person, attr)
- return nil if !person.account
- multiple = ["policy_group_ids", "filter_tags", "login_provider_ids"].include?(attr)
- value = person.account.send(attr)
- value = @person_parser.serialize(:multiple, value) if multiple
- value
+ # HELPERS
+ def _serialize_values(entry, phase = :person)
+ @person_parser.active_attrs(entry, phase, process: :serialize).each_with_object({}) do |attr, hash|
+ data = entry.is_a?(Hash)? entry.merge(hash) : entry
+ serial_attr = @person_parser.serialize(attr, data, phase, deps: @deps[attr] || {})
+ hash.merge!(hash_attr(attr, serial_attr))
+ end
end
- def _get_from_details(person, attr)
- return nil if !person.details || !person&.details&.schema_id
- unless field = person.details.get_field(attr)
- fatal("Field '#{attr}' does not exist in details of schema: '#{person.details.schema_id}'")
+ def _parse_values(entry, phase = :internal)
+ @person_parser.active_attrs(entry, phase).each_with_object({}) do |attr, hash|
+ parsed_attr = @person_parser.parse(attr, entry.merge(hash), phase)
+ hash.merge!(hash_attr(attr, parsed_attr))
end
- value = person.details[attr]
- value = @person_parser.serialize(:date, value) if field.type == "date"
- value = @person_parser.serialize(:multiple, value) if field.multiple
- value
end
- # MAPPED ENTRY (when and where applicable)
- # To obtain an entry with internal names but external values.
- # @param data [Hash] external or raw entry (when parsing) or internal or parsed entry (when serializing).
- # @return [Hash] entry with **internal names** and **external values**.
- def _mapped_entry(data)
- return _aliased_entry(data) if parsing?
- _serialized_entry(data)
+ # Transforms each **typed** value into its `String` version
+ def _serialize_type(attr, value, schema: nil)
+ case
+ when !!schema
+ unless field = schema[attr]
+ fatal("Field '#{attr}' does not exist in details of schema: '#{schema.name}'")
+ end
+ value = @person_parser.serialize(:multiple, value) if field.multiple
+ if @person_parser.defined?(field.type.to_sym)
+ value = @person_parser.serialize(field.type.to_sym, value, deps: {"attr" => attr})
+ end
+ value
+ when ["policy_group_ids", "filter_tags", "login_provider_ids", "starred_ids"].include?(attr)
+ @person_parser.serialize(:multiple, value)
+ when ["freemium", "accept_eula"].include?(attr)
+ @person_parser.serialize(:boolean, value)
+ when ["subordinates"].include?(attr)
+ @person_parser.serialize(:number, value)
+ else
+ value
+ end
end
- # Parsing helper that aliases attribute names (from internal to external names)
- # @note **Parse**: here we aliase internal attribute names into external ones.
- # @param ext_entry [Hash] entry in raw, with **external** names and values.
- # @return [Hash] entry with **internal names** and **external values**.
- def _aliased_entry(ext_entry)
- aliased_hash = @emap.aliased_attrs.map do |attr|
- [attr, ext_entry[@emap.to_external(attr)]]
- end.to_h
+ # Transforms each `String` value into its **typed** version
+ def _parse_type(attr, value, schema: nil)
+ value = value.strip if value.is_a?(String)
+ value = nil if value.to_s.strip.empty?
+ case
+ when !!schema
+ unless field = schema[attr]
+ fatal("Field '#{attr}' does not exist in details of schema: '#{schema.name}'")
+ end
+ value = @person_parser.parse(:multiple, value) if field.multiple
- ext_entry.slice(*@emap.direct_attrs).merge(aliased_hash)
+ if @person_parser.defined?(field.type.to_sym)
+ value = @person_parser.parse(field.type.to_sym, value, deps: {"attr" => attr})
+ end
+ value
+ when attr == "email"
+ value = value.strip.downcase if value
+ value
+ when ["policy_group_ids", "filter_tags", "login_provider_ids", "starred_ids"].include?(attr)
+ value = @person_parser.parse(:multiple, value)
+ value = (attr == "filter_tags")? value.compact.map(&:upcase) : value
+ value
+ when ["freemium", "accept_eula"].include?(attr)
+ @person_parser.parse(:boolean, value)
+ when ["subordinates"].include?(attr)
+ @person_parser.parse(:number, value)
+ else
+ value
+ end
end
- def hash_attr(attr, value)
- return value if value.is_a?(Hash)
- { attr => value }
+ # Merges multiple hashes giving overriding perference to the first ones.
+ # @return [Hash] with well sorted keys, as they came in the order of the input hashes.
+ def merging(*hashes)
+ sorted_keys = hashes.map {|h| h.keys}.flatten.uniq
+ rev_hash = hashes.reverse.each_with_object({}) {|h, out| out.merge!(h)}
+ merged = sorted_keys.each_with_object({}) do |k, h|
+ h[k] = rev_hash[k]
+ end
+ merged = yield(merged) if block_given?
+ merged
end
- # Serializing helper that serializes values (from internal to external values).
- # @note **Serializing**:
- # 1. here we tranform internal into external **values**.
- # 2. when running the serializers, it overrides existing keys.
- # @param unserialized_entry [Hash] entry with **internal** names and values.
- # @return [Hash] entry with **internal names** and **external values**.
- def _serialized_entry(unserialized_entry)
- serial_attrs = @person_parser.defined_attrs.reduce({}) do |serial_hash, attr|
- deps = @deps[attr] || {}
- serial_attr = @person_parser.serialize(attr, @person, deps: deps)
- serial_hash.merge(hash_attr(attr, serial_attr))
- end
- unserialized_entry.merge(serial_attrs).tap do |hash|
- if hash.key?("filter_tags") && hash["filter_tags"].is_a?(Array)
- hash["filter_tags"] = @person_parser.serialize(:multiple, hash["filter_tags"])
- end
- end
+ # Adds to `dest_entry` the `keys` it misses from `source_entry`
+ def merge_missing_attrs(dest_entry, source_entry)
+ keys_rest = source_entry.keys - dest_entry.keys
+ dest_entry.merge(source_entry.slice(*keys_rest))
end
- # To obtain an entry with internal names but external values.
- # @param data [Hash, Ecoportal::API::V1::Person] alised_entry (when parsing) or person (when serializing).
- # @return [Hash] the `internal entry` with the **internal** attributes names and values.
- def _internal_entry(data)
- return _parsed_entry(data) if parsing?
- _unserialized_entry(data)
+ def into_a(value)
+ value = [] if value == nil
+ value = [].push(value) unless value.is_a?(Array)
+ value
end
- # Parsing helper that just **parses the values** that have a parser/serializer defined.
- # @param aliased_entry [Hash] the entry with the _internal attribute_ names but the _external values_.
- # @return [Hash] the `internal entry` with the **internal** attributes names and values.
- def _parsed_entry(aliased_entry)
- parsed = @person_parser.active_attrs(aliased_entry).each_with_object({}) do |attr, hash|
- hash[attr] = @person_parser.parse(attr, aliased_entry.merge(hash))
+ def get_part(obj, attr)
+ return unless obj
+ case obj
+ when Ecoportal::API::V1::PersonDetails
+ #unless field = obj.get_field(attr)
+ # fatal("Field '#{attr}' does not exist in details of schema: '#{obj.schema_id}'")
+ #end
+ obj[attr]
+ else
+ obj.send(attr)
end
- aliased_entry.merge(parsed)
end
- # Serializing helper that just creates the _internal entry_ out of a `Person` object.
- # @note
- # - when unnesting attributes, the overriding precedence for collisions is
- # - `core` -> _overrides_ -> `account` -> _overrides_ -> `details`
- # - to keep things consistent, the `internal entry` hash has keys in this order:
- # - `core`, `account`, `details`.
- # @param person [Ecoportal::API::V1::Person] the `Person` object to transform into an _internal entry_.
- # @return [Hash] the `internal entry` with the **internal** attributes names and values.
- def _unserialized_entry(person)
- core_hash = @person_parser.target_attrs_core.reduce({}) do |hash, attr|
- value = _get_from_core(person, attr)
- hash.merge(hash_attr(attr, value))
+ def set_part(obj, attr, value)
+ return unless obj
+ begin
+ case obj
+ when Ecoportal::API::V1::PersonDetails
+ unless field = obj.get_field(attr)
+ fatal("Field '#{attr}' does not exist in details of schema: '#{obj.schema_id}'")
+ end
+ obj[attr] = value
+ else
+ obj.send("#{attr}=", value)
+ end
+ rescue Exception => e
+ raise e.append_message " -- Entry #{to_s(:identify)}"
end
+ end
- details_hash = @person_parser.target_attrs_details.reduce({}) do |hash, attr|
- value = _get_from_details(person, attr)
- hash.merge(hash_attr(attr, value))
- end
-
- account_hash = @person_parser.target_attrs_account.reduce({}) do |hash, attr|
- value = _get_from_account(person, attr)
- hash.merge(hash_attr(attr, value))
- end
-
- # merge by core overriding account and details
- rh = details_hash.merge(account_hash).merge(core_hash)
- # resort hash keys
- sorted_keys = core_hash.keys | account_hash.keys | details_hash.keys
- sorted_keys.reduce({}) {|h,k| h[k] = rh[k]; h}
+ # @return [Hash] `value` if it was a `Hash`, and `{ attr => value}` otherwise
+ def hash_attr(attr, value)
+ return value if value.is_a?(Hash)
+ { attr => value }
end
# LOGGER
def logger
@logger || ::Logger.new(IO::NULL)
@@ -396,14 +478,24 @@
def fatal(msg)
logger.fatal(msg)
raise msg
end
- # HELPERS
- def into_a(value)
- value = [] if value == nil
- value = [].push(value) unless value.is_a?(Array)
- value
+ # Function to debug faste
+ def print_models
+ print_it = Proc.new do |name, model|
+ puts "#{name}:"
+ pp model
+ puts "*" * 30
+ end
+
+ fin = Proc.new {|x_| print_it.call("final_entry", @final_entry) }
+ int = Proc.new {|x_| print_it.call("internal_entry", @internal_entry) }
+ mad = Proc.new {|x_| print_it.call("mapped_entry", @mapped_entry) }
+ ext = Proc.new {|x_| print_it.call("external_entry", @external_entry) }
+
+ call_order = parsing? ? [ext, mad, int, fin] : [fin, int, mad, ext]
+ call_order.each {|proc| proc.call}
end
end
end
end