summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRobert Speicher <robert@gitlab.com>2018-09-14 17:38:29 +0000
committerRobert Speicher <robert@gitlab.com>2018-09-14 17:38:29 +0000
commit165e9a99c0363934e7676f3968e974af73c6cf95 (patch)
treeddeb4bbd45faaf3a8cd3efc8e28dd22c55a6f617 /lib
parent69925767b7ac49b59c0292608b6655edb117e31d (diff)
parentebe89e8bd259a848d737b33a793298220054a023 (diff)
downloadgitlab-ce-165e9a99c0363934e7676f3968e974af73c6cf95.tar.gz
Merge branch '50824-fix-prepend-concern' into 'master'
CE: Properly implement prepending for Concern See merge request gitlab-org/gitlab-ce!21444
Diffstat (limited to 'lib')
-rw-r--r--lib/gitlab/patch/prependable.rb65
-rw-r--r--lib/gitlab/utils/override.rb12
2 files changed, 73 insertions, 4 deletions
diff --git a/lib/gitlab/patch/prependable.rb b/lib/gitlab/patch/prependable.rb
new file mode 100644
index 00000000000..a9f6cfb19cb
--- /dev/null
+++ b/lib/gitlab/patch/prependable.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+# We're patching `ActiveSupport::Concern` in
+# config/initializers/0_as_concern.rb
+#
+# We want to patch `ActiveSupport::Concern` for two reasons:
+# 1. Allow defining class methods via: `class_methods` method
+# 2. Allow `prepended do; end` work like `included do; end`
+# If we don't need anything above, we don't need this patch nor the concern!
+
+# 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
+
+ def prepend_features(base)
+ return false if prepended?(base)
+
+ super
+
+ if const_defined?(:ClassMethods)
+ klass_methods = const_get(:ClassMethods)
+ base.singleton_class.prepend klass_methods
+ base.instance_variable_set(:@_prepended_class_methods, klass_methods)
+ end
+
+ if instance_variable_defined?(:@_prepended_block)
+ base.class_eval(&@_prepended_block)
+ end
+
+ true
+ end
+
+ def class_methods
+ super
+
+ if instance_variable_defined?(:@_prepended_class_methods)
+ const_get(:ClassMethods).prepend @_prepended_class_methods
+ 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)
+
+ base.ancestors[0...index].index(self)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
index 7b2a62fed48..d00921e6cdc 100644
--- a/lib/gitlab/utils/override.rb
+++ b/lib/gitlab/utils/override.rb
@@ -89,15 +89,19 @@ module Gitlab
def included(base = nil)
super
- queue_verification(base)
+ queue_verification(base) if base
end
- alias_method :prepended, :included
+ def prepended(base = nil)
+ super
+
+ queue_verification(base) if base
+ end
- def extended(mod)
+ def extended(mod = nil)
super
- queue_verification(mod.singleton_class)
+ queue_verification(mod.singleton_class) if mod
end
def queue_verification(base)