Ruby on rails 调用基于超级的被调用方值
方法Ruby on rails 调用基于超级的被调用方值,ruby-on-rails,ruby,super,Ruby On Rails,Ruby,Super,方法super基于\uuuuu方法\uuuu调用父方法。 如何基于被调用方调用父方法 class SomeLogic DICTIONARY = { new_method_1: 'dictionary value 1', new_method_2: 'dictionary value 2' } def initialize(method_name) @method_name = method_name end def call DICTION
super
基于\uuuuu方法\uuuu
调用父方法。
如何基于被调用方调用父方法
class SomeLogic
DICTIONARY = {
new_method_1: 'dictionary value 1',
new_method_2: 'dictionary value 2'
}
def initialize(method_name)
@method_name = method_name
end
def call
DICTIONARY[@method_name]
end
end
module M
extend ActiveSupport::Concern
def base_method
logic = SomeLogic.new(__callee__).call
if logic
logic
elsif defined?(__callee__)
super # here analogue of super needed
else
{}
end
end
alias_method :new_method_1, :base_method
alias_method :new_method_2, :base_method
alias_method :new_method_3, :base_method
end
class A
prepend M
def new_method_3
'foo'
end
end
预期成果:
A.new.new_method_1 # dictionary value 1
A.new.new_method_2 # dictionary value 2
A.new.new_method_3 # foo
目前的结果:
A.new.new_method_1 # dictionary value 1
A.new.new_method_2 # dictionary value 2
A.new.new_method_3 # no superclass method `base_method' for A
如果你改变
class A
prepend M
到
您将获得所需的输出好的,因此这非常复杂,但它将按要求工作
class SomeLogic
DICTIONARY = {
new_method_1: 'dictionary value 1',
new_method_2: 'dictionary value 2'
}
def initialize(method_name)
@method_name = method_name
end
def call
DICTIONARY[@method_name]
end
end
module M
def self.prepended(base)
base.extend(ClassMethods)
end
def base_method(&block)
SomeLogic.new(__callee__).call ||
block&.call || # ruby < 2.3 block && block.call
{}
end
module ClassMethods
def method_added(method_name)
if M.instance_methods.include?(method_name)
orig = M.instance_method(method_name)
M.remove_method(method_name)
new = self.instance_method(method_name)
self.prepend(Module.new do
define_method(method_name) do
result = orig.bind(self).call(&new.bind(self))
end
end)
M.define_method(method_name, &orig.bind(M))
end
end
end
alias_method :new_method_1, :base_method
alias_method :new_method_2, :base_method
alias_method :new_method_3, :base_method
alias_method :new_method_4, :base_method
end
class A
prepend M
def new_method_3
'foo'
end
end
class B
prepend M
end
如果您更喜欢include
而不是prepend
,那么M
可能看起来像
module M
def self.included(base)
super
base.extend(ClassMethods)
end
def base_method
if logic = SomeLogic.new(__callee__).call
logic
elsif self.class.instance_methods(false).include?(__callee__)
send(__callee__,true)
else
{}
end
end
module ClassMethods
def method_added(method_name)
return if @_adding_method # avoid stack level issues
if M.instance_methods.include?(method_name)
new = instance_method(method_name)
@_adding_method = true # avoid stack level issues
define_method(method_name) do |bypass_parent=false|
return super() unless bypass_parent
new.bind(self).call
end
@_adding_method = false
end
end
end
end
如果
SomeLogic::DICTIONARY
具有:new\u method\u 3
的键,则包含将不起作用,因为此逻辑似乎需要优先于已定义的方法调用
p A.new.new_method_1
#=> 'dictionary value 1'
p A.new.new_method_2
#=> 'dictionary value 2'
p A.new.new_method_3
#=> 'foo'
p A.new.new_method_4
#=> {}
p B.new.new_method_3
#=> {}
module M
def self.included(base)
super
base.extend(ClassMethods)
end
def base_method
if logic = SomeLogic.new(__callee__).call
logic
elsif self.class.instance_methods(false).include?(__callee__)
send(__callee__,true)
else
{}
end
end
module ClassMethods
def method_added(method_name)
return if @_adding_method # avoid stack level issues
if M.instance_methods.include?(method_name)
new = instance_method(method_name)
@_adding_method = true # avoid stack level issues
define_method(method_name) do |bypass_parent=false|
return super() unless bypass_parent
new.bind(self).call
end
@_adding_method = false
end
end
end
end