Get your filthy hands off my Kernel methods

Using pre-existing libraries can save you development time. Unfortunately, the quality of Ruby plugins and gems can be highly variable.

Kernel#__method__ as defined in the aws-s3 gem:

unless (RUBY_VERSION[0,3] == '1.9')
  module Kernel
    def __method__
      /\`([^\']+)\'/.match(caller(1).first)[1].to_sym
    end 
    # ...
  end
end

Kernel#__method__ as defined in the facets gem:

module Kernel
  def __method__(depth = 0)
    caller[depth][/`([^']+)'/, 1]
  end if RUBY_VERSION <= '1.8.7'
  # ...
end

Can you guess what happens when both are loaded?

One definition wins. Something breaks.

So which one is right?

Neither.

Please don’t write code like this.

Comments

Skip to the comment form

  1. Kerry Burke

    Wrote at 2009-06-01 12:37 UTC using Firefox 3.0.10 on Linux:

    Hi, you are of course correct, code like this invariably breaks. What are the alternatives?
  2. Paul Battley

    Wrote at 2009-06-01 13:20 UTC using Firefox 3.0.10 on Mac OS X:

    The alternatives? The obvious one is to write methods in your application’s own namespace.

    Let’s take the grab-bag of anti-social practices that is aws-s3’s extensions.rb as an example.

    expirable_memoize shouldn’t be defined on Kernel at all. Put it in a module. Include the module where it’s needed. Sit back in the secure knowledge that you haven’t broken any other code.
  3. coderrr

    Wrote at 2009-06-02 23:31 UTC using Firefox 3.0.10 on Linux:

    or install the monkey shield!

    http://github.com/coderrr/monkey_shield/tree/master

    :)
  4. pete

    Wrote at 2009-06-02 23:46 UTC using Firefox 3.0.10 on Linux:

    Yikes, I just moved a project from aws-s3 to right_aws, and I’m glad I did.

    Reg Braithwaite has written a few blogs about this recently too.
  5. cldwalker

    Wrote at 2009-06-02 23:53 UTC using Firefox 3.0.10 on Mac OS X:

    Facets is a great resource of ruby extensions. Like u, I don’t understand why the author chose to share them in an antisocial way. Sadly, most ruby extension libraries do the same.
  6. hurbl

    Wrote at 2009-06-03 01:06 UTC using Firefox 3.0.10 on Windows XP:

    > Please don’t write code like this.
    You mean Ruby? Haw haw haw nurk nurk cough sorry
  7. khelll

    Wrote at 2009-06-03 03:36 UTC using Firefox 3.0.10 on Linux:

    Are you against monkey patching or what?
  8. Marc-André Lafortune

    Wrote at 2009-06-19 18:17 UTC using Firefox 3.0.11 on Mac OS X:

    I completely agree with the essence of what you are saying. On the other hand, Kernel_method_ is standard in Ruby 1.9, so I wouldn’t blame aws-s3 to define it in a compatible fashion.

    The culprit here is ‘facets’ which defines it to something else than Ruby 1.9’s definition (returning a string instead of a symbol, and taking an optional argument). The fact that it is not monkeypatching it in Ruby 1.9 means that it either it doesn’t work in Ruby 1.9 or it doesn’t call Kernel_method_ at all. It would also break in the upcoming Ruby 1.8.8; the conditional should check agains “1.9” (or better, use method_defined)

    I’m not implying that aws-s3 is good code. I had to submit a patch and also wrote a blog post on aws-s3’s code. I just mean that extending builtin classes in a forward compatible fashion shouldn’t cause incompatibilities. Maybe I’m biased because of my backports gem ! :-)

Leave a comment

Please read the comment guidelines before posting. Comments are Gravatar-enabled. Your email address will not be published.

To prove that you’re human, type human in the Bot check field.

Trying to post some program output or a long code sample? Please use a paste service and link to it instead.