And*_*ini 25 ruby ruby-2.0 refinements
Module#refine
method接受一个类和一个块并返回一个细化模块,所以我想我可以定义:
class Class
def include_refined(klass)
_refinement = Module.new do
include refine(klass) {
yield if block_given?
}
end
self.send :include, _refinement
end
end
Run Code Online (Sandbox Code Playgroud)
并且以下测试通过
class Base
def foo
"foo"
end
end
class Receiver
include_refined(Base) {
def foo
"refined " + super
end
}
end
describe Receiver do
it { should respond_to(:foo) }
its(:foo) { should eq("refined foo") }
end
Run Code Online (Sandbox Code Playgroud)
因此,使用细化,我可以将类转换为模块,动态改进其行为,并将其包含在其他类中.
在rb_mod_refine的C实现中 我们看到了
refinement = rb_module_new();
RCLASS_SET_SUPER(refinement, klass);
Run Code Online (Sandbox Code Playgroud)
这只是将精炼的超类设置为klass
复制模块中的类的实现吗?
Class#include_refined
?从改进中提取这个方面是否合理?在本地"修补"而不是使用"使用"开关激活优化?安德里亚,谢谢您在评论中提供的信息。请原谅我缺乏知识来理解这确实是必要的,尽管根据您的研究这听起来是可行的。
我认为我们不需要在 Rails 中做那么低的级别。
如果我要在引擎上做类似的事情,我会尝试以下想法,从简单到困难。
在routes.rb中,将整个引擎安装在正确的路线上。
恐怕这个最常见的用法不能满足您的需求
在routes.rb中,为应用程序路由中的特定控制器定制引擎的路由。
Devise,作为一个引擎,可以轻松做到。但我知道并不是每个引擎都能做到这一点。
在routes.rb中,将特定或整组路由重定向到引擎的路由
在应用程序的操作中,重定向到应用程序操作中的特定引擎的操作。
这应该针对特定操作进行足够的定制
class FoosController < ApplicationController
def foo
redirect_to some_engine_path if params[:foo] == 'bar'
end
Run Code Online (Sandbox Code Playgroud)继承引擎的控制器 - 用于一组操作,如果以上所有内容都不适合
*引擎的类在所有应用程序中都可用,您可以从它们继承控制器,而不是普通的ApplicationController。
# class FoosController < ApplicationController
class FoosController < BarEngine::BarsController
Run Code Online (Sandbox Code Playgroud)
*由于大多数引擎的控制器都继承自ApplicationController,这种继承仍然允许您使用ApplicationController中自己的东西,没有任何不良影响。
如果以上都不能做到,我可以尝试在本地或从我的 github 存储库提供定制服务。
总而言之,上述应该能够解决大多数情况,并且在可能和需要的情况下我自己更喜欢#5。