This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: Traits? I don't need no stinking Traits!
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
Well, it finally happened. Seven years, eight months, 17 days, 8 hours, 12 minutes and 23 seconds since I first started using Ruby, it happened.
I had a method name collision with a mixed-in module. One of my own modules, too. Here's what happened.
I decided to take a stab at fixing Terminator for Windows. It uses the sucktackular tempfile library that ships with the Ruby standard library. I wanted to use my own file-temp, but I don't have my C development environment setup completely for the new laptop. Since I already had a partially complete pure Ruby version for Windows, I decided to go ahead and finish it up.
After adding a couple more functions and constants to the windows-pr library, I hit this snag:
class FileTemp < File
include Windows::MSVCRT::IO
end
Whoops! You see, Ruby's File class has its own File#close method. But, the Windows::MSVCRT::IO module also has an close method (the C function), which overrode the core File method. Blam!
OMG WHAT WILL YO DO BETTER CALL DR SCHARLI AND IMPLEMENT TRAITS AS A CORE LANGUAGE FEATURE YOU STUPID RUBY PROGRAMMERS I TOLD YOU THIS WOULD HAPPEN SOMEDAY.
Er, no. See, once upon a time, in a gvim editor far, far away, I wrote a library called use to deal with just this scenario. I originally wrote it as an academic exercise to silence some Perl programmers, but lo and behold, I actually needed it now. (Also, I discovered a bug in it that I promptly fixed and released, but never mind that).
So, with my library in hand, I used fine grained mixins to only include the methods from the module that I actually needed:
require 'use'
class File::Temp
include Windows::MSVCRT::IO, :include => [:tmpfile, :tmpnam]
...
end
Fixed!
Er, not quite. It turns out that Windows does not support the mkstemp() function. Writing a custom one is easy, but there was one problem - I needed the MSVCRT open() function to implement it. I happen to know that the open-uri library has a global open method, so I wanted to avoid a conflict.
OMG WHAT ARE YOU GOING TO DO NOW YOU CAN'T MIX IT IN WITHOUT OVERRIDING THE OPEN-URI METHOD BUT YOU NEED TO MIX IT IN TO IMPLEMENT MKSTEMP YOU SHOULD HAVE USED A REAL LANGUAGE LIKE SCALA YOU STUPID RUBY PROGRAMMER.
Er, relax bud. You see, one of the other things you can do with the use library is alias methods on the fly when you mix them in. So, the final fix was this:
class FileTemp < File
use Windows::MSVCRT::IO,
:include => [:tmpfile, :tmpnam],
:alias => {:open, :msvcrt_open}
...
end
In my custom mkstemp()function then, I just changed 'open' to 'msvcrt_open', and bingo, no worries.