class SelfishAssociations::PathMerger

Attributes

paths[R]

Public Class Methods

new(paths) click to toggle source
# File lib/selfish_associations/utils/path_merger.rb, line 5
def initialize(paths)
  @paths = paths.select(&:present?)
end

Public Instance Methods

denillify(paths) click to toggle source

Strip off the nil endpoints in a merged nillified Hash path Array. 1-deep paths get un-Hashed. I.e., {key => nil} becomes just key. >1-deep Hashes are guaranteed to have Hash values. So, from above,

{:a => {:b => {:c => nil}, {:x => nil}}}

now becomes

{:a => [:x, {:b => :c}]}
# File lib/selfish_associations/utils/path_merger.rb, line 57
def denillify(paths)
  singles, hashes = paths.keys.partition{|k| paths[k].nil?}
  hashes.each{|k| paths[k] = denillify(paths[k])}
  return_array = singles
  return_array << paths.slice(*hashes) if hashes.present?
  return return_array.length == 1 ? return_array.first : return_array
end
hashify_path(path) click to toggle source

Convert each association index array into a 1-wide, n-deep Hash For algorithmic convenience (see below), applies a nil endpoint to all paths. So

[:a, :b, :c]

becomes

{:a => {:b => {:c => nil}}}
# File lib/selfish_associations/utils/path_merger.rb, line 24
def hashify_path(path)
  path.reverse.reduce(nil){|path_partial, node| {node => path_partial}}
end
merge() click to toggle source

Take array of arrays in @paths and turn into a nested hash Duplicate keys are collapsed into Array values Endpoint values are guaranteed to be Arrays

# File lib/selfish_associations/utils/path_merger.rb, line 12
def merge
  merged_paths = @paths.reduce({}){|merged, path| merge_paths(merged, hashify_path(path))}
  return denillify(merged_paths)
end
merge_paths(paths, new_path) click to toggle source

Merge in a new hash path into the current merged hash paths. Dup keys are combined as a merged Hash themselves: we need recursion! Non-nil values are guaranteed to be Hashes because we've introduced the nil endpoint Therefore we can simply merge all non-nil values recursivelye So

[[:a, :b, :c], [:a, :b], [:a, :x]

which hashifies into (remembering that we add nil endpoints)

[{:a => {:b => {:c => nil}}}, {:a => {:b => :nil}}, {:a => {:x => nil}}]

now becomes

{:a => {:b => {:c => nil}, {:x => nil}}}
# File lib/selfish_associations/utils/path_merger.rb, line 38
def merge_paths(paths, new_path)
  paths.merge!(new_path) do |parent_node, oldval, newval|
    if oldval.nil? || newval.nil?
      # If either old or new path ended at parent_node, use the other
      oldval || newval
    else
      # Else both paths continue from this node: recurse down the path!
      merge_paths(oldval, newval)
    end
  end
end