Skip to content

Instantly share code, notes, and snippets.

@maxjacobson
Last active December 29, 2015 00:09
Show Gist options
  • Save maxjacobson/7584201 to your computer and use it in GitHub Desktop.
Save maxjacobson/7584201 to your computer and use it in GitHub Desktop.
I was always pet peeved that Array#second didn't exist when Array#first and Array#last do wouldn't this be fun? haha
# gem install numbers_in_words
require 'numbers_in_words'
require 'numbers_in_words/duck_punch'
class Array
def method_missing(m)
self[m.to_s.gsub(/\_/, ' ').in_numbers - 1]
end
end
nums = (1..100).to_a
puts nums.first #=> 1
puts nums.second #=> 2
puts nums.third #=> 3
puts nums.fourth #=> 4
puts nums.thirty_five #=> 35
puts nums.thirty_fifth #=> 30 (bug)
# I just want to acknowledge that I'm using `#=>` incorrectly. That's supposed to indicate the return value, but I'm using it to indicate the output.
@carlosplusplus
Copy link

Your implementation here is quite clever and I commend you for it.
However, it's incorrect to call puts nums.thirty_fifth a bug at all.

I actually poked around in the source for numbers_in_words and found no indication that they handled the "n-th" representation of numbers. In fact, "thirty_fifth" isn't a number, but rather, it represents a relative ordering of a particular object. Interesting then... so if the code doesn't support "n-th" representations of numbers, how is your code working?

I added pry-debugger into the project and put it into method_missing like so:

require 'pry-debugger'

class Array
  def method_missing(m)
    binding.pry
    self[m.to_s.gsub(/\_/, ' ').in_numbers - 1]
  end
end

And this was my console output:

ruby niw.rb
1
2
3
4
5

From: /Users/clazo1271/Desktop/niw.rb @ line 7 Array#method_missing:

    6: def method_missing(m)
 => 7:  binding.pry
    8:   self[m.to_s.gsub(/\_/, ' ').in_numbers - 1]
    9: end

[1] pry(#<Array>)> puts m
thirty_five
=> nil

Whoa - so .thirty_five is the first method that triggers method_missing.

This immediately tells me that .second, .third, .fourth, etc. can't possibly be triggered by your method_missing (as I expected from the gem source code). I then threw a pry statement right before the call to nums.second and did a step call to see where that function ended up:

From: /Users/clazo1271/Desktop/niw.rb @ line 16 :

    11:
    12: nums = (1..100).to_a
    13:
    14: puts nums.first        #=> 1
    15: binding.pry
 => 16: puts nums.second       #=> 2
    17: puts nums.third        #=> 3
    18: puts nums.fourth       #=> 4
    19: puts nums.fifth        #=> 5
    20: puts nums.thirty_five  #=> 35
    21: puts nums.thirty_fifth #=> 30 (bug)

[2] pry(main)> step

From: /Users/clazo1271/.rvm/gems/ruby-1.9.3-p448/gems/activesupport-4.0.1/lib/active_support/core_ext/array/access.rb @ line 26 Array#second:

    25: def second
 => 26:   self[1]
    27: end

So, it appears that these functions are being implemented by ActiveSupport and not by your method_missing. A quick grep through the source code proves this point. Check out Line 1 from numbers_in_words.rb:

require 'active_support/core_ext/array'

To summarize - the code is behaving completely as expected.
The original method magic is happening through ActiveSupport.

Therefore, puts nums.thirty_fifth isn't actually a bug. QED. :-)

@maxjacobson
Copy link
Author

@cjlwired I'll double check later but ... I'm pretty sure I'm not using active support. unless active support is a dependency of numbers_in_words

@maxjacobson
Copy link
Author

oh, I see now that you said that

@maxjacobson
Copy link
Author

so that means I can use .second in my rails apps, who knew?

but I maintain that it's a bug because the interface is inconsistent. I don't mean it's a bug in that gem, I mean a bug in my implementation. if I can do [].second then I should be able to do [].thirty_fifth

@carlosplusplus
Copy link

Yes, if you're tying the bug to your interface, then I agree completely. We both now know that the numbers_to_words gem cannot handle "-nd" || "-th processing, so that's something you'll have to account for.

Either way, this is a cool implementation and was a good excuse to pry into someone else's code.
GET IT?! ❤️ ❤️ ❤️

@maxjacobson
Copy link
Author

@cjlwired thanks for breaking it down btw, I never would have thought it was leaning on active support if you hadn't dug into the source <3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment