让我们有一些提供API的模块或gem(或它们的池)。 Teese API我们无法修改。 API具有需要blok的界面。让API调用MyClass
并使用方法foo
来重新阻止阻塞。我们需要编写足够的代码来阻止内容。我们需要编写这些块的nubmer。因此,我们拥有许多具有此类API的模块,这些模块需要块的实现以及API的块实现数量。我们将块代码称为some code
。这种情况的完整代码示例如下所示:
MyClass.foo do
some code
end
在这个简短的示例中,我们可以看到使用方法MyClass
的课程foo
,并在其中阻止我们的some code
。
让我们想要在块或整个块中轻松替换类和方法以及代码。我们需要为块实现的每个变体重构移动块到lib (或移动到gem)。
我在回答之后写了问题,问题无法回答,所以我需要使用...
而不是问ruby sintax。没有阻塞或没有我们的实现的重构代码some come
(它移动到lib)看起来像这样:
MyClass.foo ...
现在在重构期间创建了新库,其中要求ruby代码未知并表示为...
。看起来像这样:
lib/Lib.rb
:
...
some code
...
在库中我们可以看到我们的实现some code
或阻塞我们的some code
,并且需要查看另一个解决任务所需的ruby特定sintax。
在上面的示例中,我需要编写的内容代替...
。我想知道进行此类重构的所有可能的躲闪,笔触,方法和接收,以及此任务的所有可能解决方案,以便轻松组合给定的API和现成的实现。
答案 0 :(得分:1)
答案在很大程度上取决于some code
中Lib.rb
的存储方式。我假设它不是像脚本中那样的独立代码,而是包含在Proc
,函数或(类/模块)方法中。您可以做的只是将原始块中的some code
更改为对相应对象的调用,如下所示:
Proc
在Lib.rb
some_code = proc { some code } # or
some_code = Proc.new { some code } # or
some_code = lambda { some code } # or
some_code = -> { some code }
电话:
MyClass.foo do
some_code.call # or
some_code[] # or
some_code.()
end
在Lib.rb
:
def SomeClass
def some_code
some code
end
end
电话:
# Somewhere else
some_instance = SomeClass.new
MyClass.foo do
some_instance.some_code
end
在Lib.rb
:
class SomeClass
def self.some_code
some code
end
end
电话:
MyClass.foo do
SomeClass::some_code
end
一个有趣的替代方法是将事物作为显式参数传递,然后Ruby将其解释为块。接受块的每个函数f
都可以这样调用:
f(other, parameters, &something)
&
前面的something
指示Ruby在to_proc
上调用Proc
(如果它还不是something
)并传递结果作为f
期望的块。
something
重新审视的方式取决于Lib.rb
:
Proc
s MyClass.foo(&some_code)
MyClass.foo(&some_instance.method(:some_code))
这个很棘手,因为它们实际上基本上是元类的实例方法,你可以这样得到:
SomeMetaClass = class << SomeClass; self; end
然后你可以按照上面的步骤继续:
MyClass.foo(SomeMetaClass.method(:some_code))