1

I wrote a small .rb tool that used the "blank?" method. I want my program to continue to work if invoked directly by ruby. I Monkey Patched Object with code below but I don't want to monkey patch when running under Rails. What can I do?

class Object def blank? respond_to?(:empty?) ? (respond_to?(:strip) ? strip.empty? : !!empty?) : !self end end 
3
  • Unless your rails project loads this file, it should not get evaluated when Rails boots. Where does this "program" live? Commented Oct 31, 2018 at 21:54
  • Also WHY do you need this monkey patch? It's pretty far-reaching. Commented Oct 31, 2018 at 22:08
  • It is a library / tool. I need this monkey patch when invoked directly using ruby. Commented Oct 31, 2018 at 22:34

2 Answers 2

4

The first thing to keep in mind is that monkey-patching a class directly — that is, opening a class to define a new method — is discouraged. It works, but it's not very flexible and it's considered a code smell.

A more sensible approach to monkey-patching is to define your methods in a mixin and then including it in a class.

This also allows you to conditionally include the mixin. For example, a common requirement in Ruby Gems is to only implement or define something if another library is (already) loaded. A common way to do this is to check if a constant from that library is defined. For example, in your case you could do this:

module PresenceExtensions def blank? respond_to?(:empty?) ? (respond_to?(:strip) ? strip.empty? : !!empty?) : !self end end unless Module.const_defined?("Rails") || Object.method_defined?(:blank?) Object.include PresenceExtensions end 

Another common technique is to try to load a gem and then add your alternative monkey-patch only if the gem is not available:

begin require "active_support/core_ext/object/blank" rescue LoadError Object.include PresenceExtensions end 

This technique has the advantage that will tell you immediately if the gem is not available, so that you don't have to worry about load order.

Sign up to request clarification or add additional context in comments.

Comments

0

Rails by default should not load a file at runtime unless it is expected to through some kind of configuration either by default or an initializer etc. If this class definition just sits inside your lib/monkey.rb for example, Rails won't auto-load it unless you tell it to.

You can test this out in your rails console if you are using pry.

Just do:

rails c # inside your console: show-method Object.blank? # this should show you the actual method definition which should be somthing # like: From: /Users/myself/.rvm/gems/ruby-2.5.1/gems/activesupport-4.2.10/lib/active_support/core_ext/object/blank.rb @ line 16: Owner: Object Visibility: public Number of lines: 3 def blank? respond_to?(:empty?) ? !!empty? : !self end 

But if rails had loaded your lib file, you would see instead that definition which you can force in the console with require

require './lib/monkey.rb' show-method Object.blank? From: /Users/myself/some/rails/project/lib/monkey.rb @ line 2: Owner: Object Visibility: public Number of lines: 4 def blank? puts "this is a monkey patch" respond_to?(:empty?) ? (respond_to?(:strip) ? strip.empty? : !!empty?) : !self end 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.