简体   繁体   English

使用Ruby别名来扩展Gem

[英]Using Ruby alias to extend a Gem

This is more a theoretical question, but I am curious anyway. 这更像是一个理论问题,但无论如何我很好奇。 I am a ruby / ruby on rails newbie (but with a lot of ancient experience in other languages / frameworks) so this is mainly a curious / learning question. 我是一个ruby / ruby​​ on rails newbie(但在其他语言/框架方面有很多古老的经验)所以这主要是一个好奇/学习的问题。 Thanks in advance for any help! 在此先感谢您的帮助!

I thought I could do a quick extension to a ruby gem using alias as follows: 我以为我可以使用别名快速扩展到ruby gem,如下所示:

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

Then in some initialization file I do: 然后在一些初始化文件中我做:

Foo::SomeControllerInFoo.send :include, InstallMyExtension

I learned this technique in the Radiant CMS where its used all over the place to extend base behavior. 我在Radiant CMS中学到了这种技术,它在整个地方使用它来扩展基本行为。 I understand this technique is now disapproved of, but it seemed like a quick way to just try some ideas out, before forking a branch on the gem, etc, etc 我知道这种技术现在已被拒绝了,但它似乎是一种快速的方法来尝试一些想法,然后在宝石上分支等等。

First off is there a better way in Rails 3 to do a quick hack extension like this (which might be useful just to test a theory, before forking the gems etc???) 首先,在Rails 3中有一个更好的方法来做这样的快速黑客扩展 (这可能只是为了测试一个理论,在分配宝石之前等等)

Second off, its not working, and there are multiple things I don't understand 第二关,它不工作,有很多我不明白的事情

Then let me explain the weirdness I am seeing: 然后让我解释一下我所看到的奇怪之处:

Even if I do do the the "include" as shown above , when I go into the console I see some really weird behavior, that I don't understand: 即使我如上所示执行“包含” ,当我进入控制台时,我看到一些非常奇怪的行为,我不明白:

1) I type Foo::SomeControllerInFoo i get back Foo::SomeControllerInFoo as I would expect. 1)我键入Foo :: SomeControllerInFoo我得到了Foo :: SomeControllerInFoo,正如我所料。 HOWEVER if run the same exact expression a second time, Foo::SomeControllerInFoo comes back undefined! 但是,如果第二次运行相同的表达式,Foo :: SomeControllerInFoo会返回undefined!

2) Just to play around I did foo = Foo::SomeControllerInFoo, and then I can do foo.send, foo.methods, whatever I like, but only if I save the copy of the class in foo! 2)只是为了玩我foo = Foo :: SomeControllerInFoo,然后我可以做foo.send,foo.methods,无论我喜欢什么,但只有我在foo中保存类的副本! What's with that? 那是什么?

3) If I now do foo.send :include, MyExtension the behavior within the debug console is as expected (ie the original class contained in the gem now has my behavior added to it.) HOWEVER running the same code during initialization has no effect. 3)如果我现在执行foo.send:include,MyExtension调试控制台中的行为是预期的(即gem中包含的原始类现在已经添加了我的行为。)但是,在初始化期间运行相同的代码无效。 Nothing breaks, but the controller is not extended. 没有什么破坏,但控制器没有扩展。

Weird that it doesn't work, I just tried again to be sure and that does the trick (put this code in a file within config/initializers ). 奇怪的是,它不起作用,我只是再次尝试确保这一点(将此代码放在config/initializers中的文件中)。

I always use a shortcut: 我总是使用快捷方式:

alias_method_chain :some_method_in_gem, :my_extension

instead of the two aliases lines, but it's exactly the same. 而不是两个别名行,但它完全相同。

You could overwrite some methods much more easily using class_eval directly. 您可以直接使用class_eval更轻松地覆盖某些方法。 Again in an initializer: 再次在初始化器中:

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

Sorry but no added value for your other questions: seems just really weird and buggy. 对不起,但没有其他问题的附加值:看起来真的很奇怪和马车。


Just to be sure, when you want to run the method defined in your controller, do: 只是为了确保,当您想要运行控制器中定义的方法时,请执行以下操作:

c = Foo::SomeControllerInFoo.new
c.method_name

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM