使用Ruby别名来扩展一个Gem

3
这是一个理论问题,但我还是很好奇。我是Ruby/Ruby on Rails的初学者(但在其他语言/框架方面有着丰富的经验),所以这主要是一个好奇/学习的问题。感谢您提供的任何帮助! 我想我可以使用别名来快速扩展一个Ruby宝石,如下所示:
module InstallMyExtension
  def self.included(base)
    base.class_eval {
      alias :some_method_in_gem_without_my_extension :some_method_in_gem
      alias :some_method_in_gem :some_method_in_gem_with_my_extension
    }
  end

  def some_method_in_gem_with_my_extension
    debugger
    # ... do fun stuff here
    some_method_in_gem_without_my_extension
  end

end

然后在某个初始化文件中,我这样做:

Foo::SomeControllerInFoo.send :include, InstallMyExtension

我在Radiant CMS中学习了这种技术,它在很多地方都用于扩展基本行为。我知道这种技术现在已经被否定了,但在分叉gem之前,试验一些想法似乎是一个快速的方法。

首先,在Rails 3中有没有更好的方法来进行快速扩展(这可能只是为了测试一个理论,在分叉gems等等之前?)

其次,它不起作用,而且有很多我不理解的东西

然后让我解释一下我看到的怪异现象:

即使我像上面所示那样“包含”,当我进入控制台时,我看到一些非常奇怪的行为,我不明白:

1)我输入Foo :: SomeControllerInFoo,我会得到Foo :: SomeControllerInFoo,就像我预期的那样。但是,如果我再次运行完全相同的表达式,Foo :: SomeControllerInFoo将返回未定义!

2)只是为了玩玩,我做了foo = Foo :: SomeControllerInFoo,然后我可以做foo.send,foo.methods,无论我喜欢什么,但只有在保存类副本foo时才能做到这一点!这是怎么回事?

3)如果我现在做foo.send:include,MyExtension,则在调试控制台中的行为与预期相同(即包含在gem中的原始类现在已添加了我的行为)。但是在初始化期间运行相同的代码没有效果。什么也不会坏,但控制器不会被扩展。

1个回答

2

很奇怪它不起作用,我再试一次确保它有用(将此代码放入config/initializers中的文件即可解决)。

我总是使用一个快捷方式:

alias_method_chain :some_method_in_gem, :my_extension

使用两个别名行的替代方案完全相同。

您可以直接使用 class_eval 更轻松地覆盖一些方法。同样在初始化器中:

Foo::SomeControllerInFoo.class_eval do
  def some_method_in_gem
   #your redefinition
  end
end

抱歉,对于您提出的其他问题,没有增加任何价值:似乎只是非常奇怪和有缺陷的。


只是为了确保,当您想要运行控制器中定义的方法时,请执行以下操作:

c = Foo::SomeControllerInFoo.new
c.method_name

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接