Commit 07da8f91 authored by Lin Jen-Shin's avatar Lin Jen-Shin

Preserve prepend semantics for Ruby

However we still want to make ClassMethods work!

And we'll need to fix codes using the wrong include/prepend
along the way. There were a lot of misuses.
parent d7f87a2b
......@@ -10,42 +10,29 @@ module Gitlab
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 prepend_features(base)
return false if prepended?(base)
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)
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
@_prepend_dependencies.each { |dep| base.prepend(dep) }
if instance_variable_defined?(:@_prepended_block)
base.class_eval(&@_prepended_block)
end
super
true
end
if const_defined?(:ClassMethods)
base.singleton_class.prepend const_get(:ClassMethods)
end
def class_methods
super
if instance_variable_defined?(:@_prepended_block)
base.class_eval(&@_prepended_block)
end
if instance_variable_defined?(:@_prepended_class_methods)
const_get(:ClassMethods).prepend @_prepended_class_methods
end
end
......@@ -63,8 +50,7 @@ module Gitlab
def prepended?(base)
index = base.ancestors.index(base)
@_prepend_dependencies.index(self) ||
base.ancestors[0...index].index(self)
base.ancestors[0...index].index(self)
end
end
end
......
......@@ -71,22 +71,41 @@ describe Gitlab::Patch::Prependable do
subject
expect(prepended_modules).to eq([[subject, ee], [subject, ce]])
expect(prepended_modules).to eq([[ce, ee]])
end
context 'overriding a method' do
before do
subject.module_eval do
def self.class_name
'Custom'
end
def name
'custom'
end
end
end
it 'returns values from the class' do
expect(subject.new.name).to eq('custom')
expect(subject.class_name).to eq('Custom')
end
end
end
describe 'a class prepending a concern prepending a concern' do
subject { Class.new.prepend(ce) }
it 'returns values from prepended module ce' do
expect(subject.new.name).to eq('ce')
expect(subject.class_name).to eq('CE')
it 'returns values from prepended module ee' do
expect(subject.new.name).to eq('ee')
expect(subject.class_name).to eq('EE')
end
it 'prepends only once' do
subject.prepend(ce)
expect(prepended_modules).to eq([[subject, ee], [subject, ce]])
expect(prepended_modules).to eq([[ce, ee], [subject, ce]])
end
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment