A gem I'm using (gem "A") relies on another gem (gem "B") whose method I'm trying to patch. When I patch gem "B" and call a method from gem "A", the monkey patch is ignored. My patch looks like the following:
module B
class<< self
def patched_method()
raise
end
end
end
I've inserted statements throughout to print the location of the method, using the form
puts B.method(:patched_method).source_location
When called before the patch, it points to the location of gem "B". After the patch it points to the location where I've defined the patch, yet it still doesn't call my patch!
Right now my patch just calls raise
so I can verify that it's being called, but I've also tried printing text and calling my actual patch code, none of which works. What am I doing wrong?
I'm trying to patch the Numerizer
gem's numerize
method which is used by the Chronic
gem.
I've tried to patch multiple ways, but the most recent were:
module NumerizerExpand
module ClassMethods
def self.numerize(value)
raise
end
end
def self.included(receiver)
receiver.extend ClassMethods
end
end
Numerizer.send(:include, NumerizerExpand)
and
Numerizer.instance_eval do
class<< self
def my_numerize(value)
puts "here"
raise
end
alias_method :numerize, :my_numerize
end
end
For the second method, I've tried using both instance_eval
and module_eval
but neither seem to work.
I've created a gist on github that contains the script I'm running to test this.
You're patching the wrong class :)
require 'numerizer'
require 'chronic'
puts Chronic::Numerizer.method(:numerize).source_location
class Chronic::Numerizer
def self.numerize(value)
puts "here"
raise
end
end
puts Chronic::Numerizer.method(:numerize).source_location
#p Chronic::Numerizer.numerize(3)
p Chronic.parse('January 2nd')
outputs
bbozo@eva:~/dev/SO_question_1$ ruby wii.rb
/home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/numerizer.rb
72
wii.rb
8
here
wii.rb:10:in `numerize': unhandled exception
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/parser.rb:100:in `pre_normalize'
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/parser.rb:226:in `tokenize'
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic/parser.rb:60:in `parse'
from /home/bbozo/.rvm/gems/ruby-2.2.3/gems/chronic-0.10.2/lib/chronic.rb:90:in `parse'
from wii.rb:17:in `<main>'
Apparently the chronic
team decided they don't want to maintain one class as a separate dependency and they just copy-pasted it and included it into the namespace.
You were patching a gem which is in reality not used by chronic
. A swine's trick :) but reasonable for the chronic
people to do.