summaryrefslogtreecommitdiff
path: root/app/models/concerns/group_descendant.rb
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@vanlanduyt.co>2017-10-04 16:56:42 +0200
committerBob Van Landuyt <bob@vanlanduyt.co>2017-10-04 22:49:42 +0200
commit06e00913f505268e0a45f4f1516a93a84600c242 (patch)
treecaa989d5a3a299cd1c1a1e6a13f90239ad1aed84 /app/models/concerns/group_descendant.rb
parent08383fd2e32b88bba1429cf9b03b493dfc6b9b3e (diff)
downloadgitlab-ce-06e00913f505268e0a45f4f1516a93a84600c242.tar.gz
Move merging of Hashes out of the `GroupDescendant` concern
Since it can technically merge any hash with objects that respond to `==`
Diffstat (limited to 'app/models/concerns/group_descendant.rb')
-rw-r--r--app/models/concerns/group_descendant.rb57
1 files changed, 4 insertions, 53 deletions
diff --git a/app/models/concerns/group_descendant.rb b/app/models/concerns/group_descendant.rb
index 11f092db2ae..6c465079753 100644
--- a/app/models/concerns/group_descendant.rb
+++ b/app/models/concerns/group_descendant.rb
@@ -5,22 +5,18 @@ module GroupDescendant
end
def self.build_hierarchy(descendants, hierarchy_top = nil)
- descendants = Array.wrap(descendants)
+ descendants = Array.wrap(descendants).uniq
return [] if descendants.empty?
unless descendants.all? { |hierarchy| hierarchy.is_a?(GroupDescendant) }
raise ArgumentError.new('element is not a hierarchy')
end
- first_descendant, *other_descendants = descendants
- merged = first_descendant.hierarchy(hierarchy_top, descendants)
-
- other_descendants.each do |descendant|
- next_descendant = descendant.hierarchy(hierarchy_top, descendants)
- merged = merge_hash_tree(merged, next_descendant)
+ all_hierarchies = descendants.map do |descendant|
+ descendant.hierarchy(hierarchy_top, descendants)
end
- merged
+ Gitlab::Utils::MergeHash.merge(all_hierarchies)
end
private
@@ -50,49 +46,4 @@ module GroupDescendant
hierarchy
end
end
-
- private_class_method def self.merge_hash_tree(first_child, second_child)
- # When the first is an array, we need to go over every element to see if
- # we can merge deeper. If no match is found, we add the element to the array
- #
- # Handled cases:
- # [Array, Hash]
- if first_child.is_a?(Array) && second_child.is_a?(Hash)
- merge_hash_into_array(first_child, second_child)
- elsif first_child.is_a?(Hash) && second_child.is_a?(Array)
- merge_hash_into_array(second_child, first_child)
- # If both of them are hashes, we can deep_merge with the same logic
- #
- # Handled cases:
- # [Hash, Hash]
- elsif first_child.is_a?(Hash) && second_child.is_a?(Hash)
- first_child.deep_merge(second_child) { |key, first, second| merge_hash_tree(first, second) }
- # If only one of them is a hash, and one of them is a GroupHierachy-object
- # we can check if its already in the hash. If so, we don't need to do anything
- #
- # Handled cases
- # [Hash, GroupDescendant]
- elsif first_child.is_a?(Hash) && first_child.keys.include?(second_child)
- first_child
- elsif second_child.is_a?(Hash) && second_child.keys.include?(first_child)
- second_child
- # If one or both elements are a GroupDescendant, we wrap create an array
- # combining them.
- #
- # Handled cases:
- # [GroupDescendant, Array], [GroupDescendant, GroupDescendant], [Array, Array]
- else
- Array.wrap(first_child) + Array.wrap(second_child)
- end
- end
-
- private_class_method def self.merge_hash_into_array(array, new_hash)
- if mergeable_index = array.index { |element| element.is_a?(Hash) && (element.keys & new_hash.keys).any? }
- array[mergeable_index] = merge_hash_tree(array[mergeable_index], new_hash)
- else
- array << new_hash
- end
-
- array
- end
end