From 71fefe147475bb85c67de95fba8211385cfb0a79 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Thu, 30 Aug 2018 19:05:00 +0800 Subject: Properly implement prepending for Concern --- lib/gitlab/patch/prependable.rb | 71 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 lib/gitlab/patch/prependable.rb (limited to 'lib/gitlab') diff --git a/lib/gitlab/patch/prependable.rb b/lib/gitlab/patch/prependable.rb new file mode 100644 index 00000000000..45fac0ed4a7 --- /dev/null +++ b/lib/gitlab/patch/prependable.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +# rubocop:disable Gitlab/ModuleWithInstanceVariables +module Gitlab + module Patch + module Prependable + class MultiplePrependedBlocks < StandardError + def initialize + super "Cannot define multiple 'prepended' blocks for a Concern" + end + end + + module MetaConcern + def extended(base) + super + base.instance_variable_set(:@_prepend_dependencies, []) + end + end + + def self.prepended(base) + super + base.singleton_class.prepend MetaConcern + end + + def append_features(base) + super + + prepend_features(base) + end + + def prepend_features(base) + if base.instance_variable_defined?(:@_prepend_dependencies) + base.instance_variable_get(:@_prepend_dependencies) << self + false + else + return false if prepended?(base) + + @_prepend_dependencies.each { |dep| base.prepend(dep) } + + super + + if const_defined?(:ClassMethods) + base.singleton_class.prepend const_get(:ClassMethods) + end + + if instance_variable_defined?(:@_prepended_block) + base.class_eval(&@_prepended_block) + end + end + end + + def prepended(base = nil, &block) + if base.nil? + raise MultiplePrependedBlocks if + instance_variable_defined?(:@_prepended_block) + + @_prepended_block = block + else + super + end + end + + def prepended?(base) + index = base.ancestors.index(base) + + @_prepend_dependencies.index(self) || + base.ancestors[0...index].index(self) + end + end + end +end -- cgit v1.2.3