开发者

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. Thanks in advance for any help!

I thought I could do a quick extension to a ruby gem using alias as follows:

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. 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???)

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. HOWEVER if run the same exact expression a second time, Foo::SomeControllerInFoo comes back 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! What's with that?

3) If I now do foo.send :include, MyExtension the behavior within the debug console is as expected (i.e. the original class contained in the gem now has my behavior added to it.) HOWEVER running the same code during initialization has no effect. 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).

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. 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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜