将ruby类转换为模块而不是使用细化的更好方法?

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)

因此,使用细化,我可以将类转换为模块,动态改进其行为,并将其包含在其他类中.

  • 是否有一种更简单的方法可以将类转换为Ruby中的模块(比如ruby <2)?
  • rb_mod_refine的C实现中 我们看到了

    refinement = rb_module_new();
    RCLASS_SET_SUPER(refinement, klass);
    
    Run Code Online (Sandbox Code Playgroud)

    这只是将精炼的超类设置为klass复制模块中的类的实现吗?

  • 我知道多重继承是通过模块完成的,但是社区会怎么想Class#include_refined?从改进中提取这个方面是否合理?在本地"修补"而不是使用"使用"开关激活优化?

Bil*_*han 1

安德里亚,谢谢您在评论中提供的信息。请原谅我缺乏知识来理解这确实是必要的,尽管根据您的研究这听起来是可行的。

我认为我们不需要在 Rails 中做那么低的级别。

如果我要在引擎上做类似的事情,我会尝试以下想法,从简单到困难。

  1. 在routes.rb中,将整个引擎安装在正确的路线上。

    恐怕这个最常见的用法不能满足您的需求

  2. 在routes.rb中,为应用程序路由中的特定控制器定制引擎的路由。

    Devise,作为一个引擎,可以轻松做到。但我知道并不是每个引擎都能做到这一点

  3. 在routes.rb中,将特定或整组路由重定向到引擎的路由

  4. 在应用程序的操作中,重定向到应用程序操作中的特定引擎的操作。

    这应该针对特定操作进行足够的定制

    class FoosController < ApplicationController
      def foo
        redirect_to some_engine_path if params[:foo] == 'bar'
      end
    
    Run Code Online (Sandbox Code Playgroud)
  5. 继承引擎的控制器 - 用于一组操作,如果以上所有内容都不适合

    *引擎的类在所有应用程序中都可用,您可以从它们继承控制器,而不是普通的ApplicationController。

    # class FoosController < ApplicationController
    class FoosController < BarEngine::BarsController
    
    Run Code Online (Sandbox Code Playgroud)

    *由于大多数引擎的控制器都继承自ApplicationController,这种继承仍然允许您使用ApplicationController中自己的东西,没有任何不良影响。

  6. 如果以上都不能做到,我可以尝试在本地或从我的 github 存储库提供定制服务。

总而言之,上述应该能够解决大多数情况,并且在可能和需要的情况下我自己更喜欢#5。

  • 感谢您的回答,但我并不是真的想开始一个关于 Rails 的话题。顺便说一句,我也更喜欢 5。正如您所指出的,“大多数”引擎控制器(请参阅 Devise)继承自“ApplicationController”,但“Tolk::ApplicationController”(我上面提到过)却没有。 (2认同)