class Eco::API::Common::People::PersonEntry
def __external_entry(data)
-
(Hash)- entry in raw: that with **external** names, values and types.
def __external_entry(data) return data if parsing? _external_serializing(data) end
def __final_entry(data)
-
(Hash)- that with **internal** names, values and types.
def __final_entry(data) return _final_parsing(data) if parsing? _final_serializing(data) end
def __internal_entry(data)
-
(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
def __mapped_entry(data)
-
(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 _external_serializing(mapped_entry)
-
(Hash)- with **external** names, values and types.
Parameters:
-
mapped_entry(Hash) -- that with **internal** names but **external** values and types.
Other tags:
- Note: - **Serialize**: here we unaliase internal attribute names into external ones.
def _external_serializing(mapped_entry) target_attrs = @emap.all_model_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 end merge_missing_attrs(external_entry, mapped_entry.slice(*rest_keys)) end
def _final_parsing(internal_entry)
-
(Hash)- the `parsed entry` with the **internal** final attributes names, values and types.
Parameters:
-
internal_entry(Hash) -- the entry with the **internal** _attribute_ names and values
def _final_parsing(internal_entry) core_account_attrs = @emap.account_attrs(internal_entry) + @emap.core_attrs(internal_entry) core_account_hash = internal_entry.slice(*core_account_attrs).each_with_object({}) do |(attr, value), hash| hash[attr] = _parse_type(attr, value) end details_attrs = @emap.details_attrs(internal_entry) details_hash = internal_entry.slice(*details_attrs).each_with_object({}) do |(attr, value), hash| hash[attr] = _parse_type(attr, value, schema: @person_parser.schema) end 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 _final_serializing(person)
-
(Hash)- the `parsed entry` with the **internal** attributes names and internal typed values.
Parameters:
-
person(Ecoportal::API::V1::Person) -- the `Person` object to transform into a _parsed entry_.
Other tags:
- Note: -
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.nil? final_entry.merge(_serialize_values(person, :person)) end end
def _internal_parsing(mapped_entry)
-
(Hash)- the `internal entry` with the **internal** attributes names and values.
Parameters:
-
mapped_entry(Hash) -- the entry with the _internal attribute_ names but the _external values_.
Other tags:
- Note: - this entry will still miss the type parsing (i.e. to `Array` if `multiple`)
def _internal_parsing(mapped_entry) mapped_entry.merge(_parse_values(mapped_entry, :internal)) end
def _internal_serializing(final_entry)
-
(Hash)- the `internal entry` with the **internal** attributes names and values, but external types.
Parameters:
-
final_entry(Hash) -- the entry with all _internal_ (attributes, values and 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 _mapped_parsing(external_entry)
-
(Hash)- entry with **internal** names, but still **external** values and types.
Parameters:
-
external_entry(Hash) -- entry in raw, with **external** names and values.
Other tags:
- Note: - **Parse**: here we aliase external attribute names into internal ones.
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
def _mapped_serializing(internal_entry)
-
(Hash)- entry with **internal** names and **external** values and types.
Parameters:
-
internal_entry(Hash) -- entry with **internal** names and values, but **external** types.
Other tags:
- Note: - **Serializing**:
def _mapped_serializing(internal_entry) mapped_hash = internal_entry.merge(_serialize_values(internal_entry, :internal)) model_attrs = @person_parser.all_model_attrs - ["send_invites"] aux_hash = mapped_hash.slice(*model_attrs) merge_missing_attrs(aux_hash, mapped_hash) end
def _parse_type(attr, value, schema: nil) # rubocop:disable Metrics/AbcSize
Transforms each `String` value into its **typed** version
def _parse_type(attr, value, schema: nil) # rubocop:disable Metrics/AbcSize value = value.strip if value.is_a?(String) value = nil if value.to_s.strip.empty? if !!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 if @person_parser.defined?(field.type.to_sym) value = @person_parser.parse(field.type.to_sym, value, deps: {"attr" => attr}) end value elsif attr == "email" value = value.strip.downcase if value value elsif %w[policy_group_ids filter_tags login_provider_ids starred_ids].include?(attr) value = @person_parser.parse(:multiple, value) value = value.compact.map(&:upcase) if attr == "filter_tags" value elsif %w[freemium accept_eula].include?(attr) @person_parser.parse(:boolean, value) elsif ["subordinates"].include?(attr) @person_parser.parse(:number, value) else value end end
def _parse_values(entry, phase = :internal)
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 end
def _serialize_type(attr, value, schema: nil)
def _serialize_type(attr, value, schema: nil) if !!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 elsif %w[policy_group_ids filter_tags login_provider_ids starred_ids].include?(attr) @person_parser.serialize(:multiple, value) elsif %w[freemium accept_eula].include?(attr) @person_parser.serialize(:boolean, value) elsif ["subordinates"].include?(attr) @person_parser.serialize(:number, value) else value end end
def _serialize_values(entry, phase = :person)
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 default_tag
def default_tag final_entry["default_tag"] end
def default_tag?
def default_tag? final_entry.key?("default_tag") end
def email
-
(String, nil)- the _email_ of this person if defined.
def email final_entry["email"] end
def email?
def email? final_entry.key?("email") end
def external_entry # rubocop:disable Style/TrivialAccessors
-
(Hash)- entry `Hash` with **external** attribute names, and values and types thereof.
Other tags:
- Note: - completely serialized entry.
def external_entry # rubocop:disable Style/TrivialAccessors @external_entry end
def external_id
-
(String, nil)- the _external id_ of this person if defined.
def external_id final_entry["external_id"] end
def external_id?
def external_id? final_entry.key?("external_id") end
def fatal(msg)
def fatal(msg) logger.fatal(msg) raise msg end
def filter_tags
def filter_tags final_entry["filter_tags"] || [] end
def filter_tags?
def filter_tags? final_entry.key?("filter_tags") end
def final_entry # rubocop:disable Style/TrivialAccessors
-
(Hash)- entry `Hash` with **internal** attribute names, values and types.
Other tags:
- Note: - values ready to be set to a person.
def final_entry # rubocop:disable Style/TrivialAccessors @final_entry end
def get_part(obj, attr)
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 end
def hash_attr(attr, value)
-
(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
def id
-
(String, nil)- the _internal id_ of this person if defined.
def id final_entry["id"] end
def id?
def id? final_entry.key?("id") end
def identify
-
(String)- string summary of this person identity.
def identify str_id = id ? "id: '#{id}'; " : "" "(row: #{idx}) '#{name}' (#{str_id}ext_id: '#{external_id}'; email: '#{email}')" end
def idx
-
(Integer)- the entry number in the input file
Other tags:
- Note: - `Eco::API::Common::People::EntryFactory#entries` adds this `idx` (i.e. row number)
def idx final_entry["idx"] end
def initialize(data, person_parser:, attr_map:, dependencies: {}, logger: ::Logger.new(IO::NULL))
-
logger(Common::Session::Logger, ::Logger) -- object to managelogs. -
dependencies(Hash) -- hash where _keys_ are internal attribute -
attr_map(Eco::Data::Mapper) -- mapper to translate attribute -
person_parser(Common::People::PersonParser) -- parser/serializer -
data(Hash, Ecoportal::API::V1::Person) -- `Person` object
Other tags:
- Note: -
def initialize(data, person_parser:, attr_map:, dependencies: {}, logger: ::Logger.new(IO::NULL)) msg = "Constructor needs a PersonParser. Given: #{person_parser.class}" raise msg unless person_parser.is_a?(Eco::API::Common::People::PersonParser) msg = "Expecting Mapper object. Given: #{attr_map.class}" raise msg if attr_map && !attr_map.is_a?(Eco::Data::Mapper) @source = data @person_parser = person_parser @deps = dependencies @logger = logger @attr_map = attr_map @emap = PersonEntryAttributeMapper.new( @source, person_parser: @person_parser, attr_map: @attr_map, logger: @logger ) if parsing? @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 @final_entry = __final_entry(@person) @internal_entry = __internal_entry(@final_entry) @mapped_entry = __mapped_entry(@internal_entry) @external_entry = __external_entry(@mapped_entry) end (print_models; exit(1)) if DEBUG # rubocop:disable Style/Semicolon end
def internal_entry # rubocop:disable Style/TrivialAccessors
-
(Hash)- entry `Hash` with **internal** attribute names and values, but **external** types.
Other tags:
- Note: - just one step away from being completely parsed (only types parsing pending).
def internal_entry # rubocop:disable Style/TrivialAccessors @internal_entry end
def into_a(value)
def into_a(value) value = [] if value.nil? value = [].push(value) unless value.is_a?(Array) value end
def logger
def logger @logger || ::Logger.new(IO::NULL) end
def mapped_entry # rubocop:disable Style/TrivialAccessors
-
(Hash)- entry `Hash` with **internal** attribute names, but **external** types and values.
def mapped_entry # rubocop:disable Style/TrivialAccessors @mapped_entry end
def merge_missing_attrs(dest_entry, 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
def merging(*hashes)
-
(Hash)- with well sorted keys, as they came in the order of the input hashes.
def merging(*hashes) sorted_keys = hashes.map(&: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
def name
-
(String, nil)- the _name_ of this person if defined.
def name final_entry["name"] end
def name?
def name? final_entry.key?("name") end
def new(data)
-
(PersonEntry)-
def new(data) self.class.new( data, person_parser: @person_parser, attr_map: @attr_map, dependencies: @deps, logger: @logger ) end
def parsing?
-
(Boolean)- returns `true` if we are **parsing**, `false` otherwise.
def parsing? !@source.is_a?(Ecoportal::API::Internal::Person) end
def policy_group_ids
def policy_group_ids final_entry["policy_group_ids"] || [] end
def policy_group_ids?
def policy_group_ids? final_entry.key?("policy_group_ids") end
def print_models
def print_models print_it = proc do |name, model| puts "#{name}:" pp model puts "*" * 30 end fin = proc { print_it.call("final_entry", @final_entry) } int = proc { print_it.call("internal_entry", @internal_entry) } mad = proc { print_it.call("mapped_entry", @mapped_entry) } ext = proc { print_it.call("external_entry", @external_entry) } call_order = parsing? ? [ext, mad, int, fin] : [fin, int, mad, ext] call_order.each(&:call) end
def serializing?
-
(Boolean)- returns `true` if we are **serializing**, `false` otherwise.
def serializing? !parsing? end
def set_account(person, exclude: nil)
-
exclude(String, Array) -- account properties that should not be set/changed to the person. -
person(Ecoportal::API::Internal::Person) -- the person we want to set the account values to.
Other tags:
- Note: - it only sets those account properties defined in the entry.
def set_account(person, exclude: nil) person.account = {} unless person.account scoped_attrs = @emap.account_attrs(@final_entry) - into_a(exclude) @final_entry.slice(*scoped_attrs).each do |attr, value| set_part(person.account, attr, value) end end
def set_core(person, exclude: nil)
-
exclude(String, Array) -- core attributes that should not be set/changed to the person. -
person(Ecoportal::API::V1::Person) -- the person we want to set the core values to.
Other tags:
- Note: -
def set_core(person, exclude: nil) scoped_attrs = @emap.core_attrs(@final_entry) - into_a(exclude) @final_entry.slice(*scoped_attrs).each do |attr, value| set_part(person, attr, value) rescue StandardError => e raise unless attr == "email" logger.error("#{e} - setting blank email instead.") set_part(person, attr, nil) end end
def set_details(person, exclude: nil)
-
exclude(String, Array) -- schema field attributes that should not be set/changed to the person. -
person(Ecoportal::API::V1::Person) -- the person we want to set the schema fields' values to.
Other tags:
- Note: - it only sets those details properties defined in the entry.
def set_details(person, exclude: nil) person.add_details(@person_parser.schema) if !person.details || !person.details.schema_id scoped_attrs = @emap.details_attrs(@final_entry) - into_a(exclude) @final_entry.slice(*scoped_attrs).each do |attr, value| set_part(person.details, attr, value) end end
def set_part(obj, attr, value)
def set_part(obj, attr, value) return unless obj case obj when Ecoportal::API::V1::PersonDetails msg = "Field '#{attr}' does not exist in details of schema: '#{obj.schema_id}'" fatal msg unless obj.get_field(attr) obj[attr] = value else obj.send("#{attr}=", value) end rescue StandardError => e # add more info to the error raise e.append_message " -- Entry #{to_s(:identify)}" end
def supervisor_id
-
(String, nil)- the _supervisor id_ of this person if defined.
def supervisor_id final_entry["supervisor_id"] end
def supervisor_id=(value)
def supervisor_id=(value) final_entry["supervisor_id"] = value end
def supervisor_id?
def supervisor_id? final_entry.key?("supervisor_id") end
def to_s(options)
-
(String)- string summary of this person identity.
def to_s(options) options = into_a(options) if options.include?(:identify) identify else final_entry.each.map do |k, v| "'#{k}': '#{v.to_json}'" end.join(" | ") end end