Files
mozo-backend/app/services/flat_keys.rb
T

53 lines
1.8 KiB
Ruby

# Transform a nested tructure indicated by dots to a structure as used by the ActiveRecord includes statement
# - dslams
# - ppls.distribution_cables
# =>
# [:dslams, {ppls: :distribution_cables}]
class FlatKeys
class << self
def as_nested_structure(ary)
return ary unless ary.first.is_a?(String)
nested_keys, flat_keys = ary.partition{|spec| spec['.']}
result = flat_keys.map(&:to_sym)
if nested_keys.any?
obj = {}
nested_keys.map{ |key| key.split('.').map(&:to_sym) }.each do |parts|
traverse_nest_structure(parts, obj)
end
result -= obj.keys
result.push obj
end
result
end
def traverse_nest_structure(parts, obj)
key = parts.shift
if parts.size == 1
case obj[key]
when nil then obj[key] = parts[0]
when Array then obj[key] |= [parts[0]]
when Hash
raise "Colliding keys for nesting of #{key} -> #{parts[0]}" unless obj[key].has_key?(parts[0])
else # expect symbol
obj[key] = Array.wrap(obj[key]).push parts[0] unless obj[key] == parts[0] # no duplicate
end
else # parts.size > 2
case obj[key]
when nil
obj[key] = {}
traverse_nest_structure(parts, obj[key])
when Array
raise "Cannot traverse #{key} -> #{parts.join('.')} because existing array value #{obj[key].inspect}"
when Hash
traverse_nest_structure(parts, obj[key])
else # expect symbol
raise "Cannot add deeper nesting for endpoing with different name #{key} -> #{obj[key]} => #{parts.join('.')}" unless obj[key] = parts[0] # same name, allows deeper nesting
obj[key] = {obj[key] => nil} # prepare for nesting
traverse_nest_structure(parts, obj[key])
end
end
end
end
end