Where to put code when monkey patching
I have used the following technique described by Justin Weiss in 3 Ways to Monkey-Patch Without Making a Mess
When in vanilla Ruby, a gem, for instance, you define a module in some file you are requiring and then include
(or extend
) the module into desired class.
module StringMonkeypatch
def foo
#your special code
end
end
String.include StringMonkeypatch
When in Rails you may want to define the module in a place that gets autoloaded (look up autoload_paths
) and in a way that follows Rails' naming convention.
For example, if monkeypatching the Sidekiq::Testing
gem class you should mirror the file structure.
# in /app/<something telling>/sidekiq/testing/monkeypatch.rb
module Sidekiq::Testing::Monkeypatch
def foo
#your special code
end
end
# in /config/environment.rb, at the bootom
Sidekiq::Testing.include Sidekiq::Testing::Monkeypatch
There is no set rule on this. Technically you can open it (the class; and add your method) anywhere. I usually make a special file called monkey_patches.rb
and put it in config/initializers
or in a misc
folder in my Rails app so if theres ever a conflict I know where to look.
Also I'd advise to use a Module
to wrap the monkey patch. Check out 3 ways to monkey patch without making a mess for more info.
His example:
module CoreExtensions
module DateTime
module BusinessDays
def weekday?
!sunday? && !saturday?
end
end
end
end
DateTime.include CoreExtensions::DateTime::BusinessDays
Just chiming in because it took me forever to figure this out because very little solutions worked.
• I had to use plain old require. I put it in the config/application.rb
file. The file does not automatically load for me if you put it in the app directory like some are suggesting. I don't know why.
patching_file_path = File.expand_path("./lib", Dir.pwd)
Dir[patching_file_path+'/*.rb'].each {|file| require file }
• I also put a temporary puts "I'm Working!
in the file I'm trying to require so I can check the console to see if it's actually loading.
• Also, if you're using spring loader, before you start your console you should do bin/spring stop
in your terminal before you start your rails console. Otherwise, it won't load new files.