Question

In watir-classic gem, we have a method called generate_ruby_code() under Element class. I would like to monkey patch it and modify few things.

What I did is:

MyFile.rb


require 'watir-classic'
module Watir
    class Element
        def generate_ruby_code(element, method_name, *args)
            puts "Print this"
        end
    end
end

But instead of calling my monkey patched method, the original generate_ruby_code in the Element class is called everytime which I don't want to happen.

Please help me to solve this issue.

Was it helpful?

Solution

Problem

I assume that you are using watir-classic v3.7.0 or older.

In these versions, doing require 'watir-classic' does not load all of the classes immediately. Some of the classes, including the Watir::Element, are not loaded until a browser instance is created.

This means that:

# Does not create Watir::Element#generate_ruby_code yet
require 'watir-classic'

# You create a Watir::Element#generate_ruby_code method
module Watir
    class Element
        def generate_ruby_code(element, method_name, *args)
            puts "Print this"
        end
    end
end

# Watir loads the Watir::Element#generate_ruby_code, which overrides yours
browser = Watir::Browser.new

My understanding is that this is due tp watir-classic previously supporting multiple browsers - ie FireWatir and SafariWatir. Various classes were autoloaded based on the browser being used.

Solution 1 - Upgrade to v4.0 or later

The easiest solution is to upgrade your watir-classic to v4.0 or later (current latest is 4.0.1).

The autoloading was removed in this version, which means your code will now work as is.

Solution 2 - Initialize browser first

If upgrading is not an option, you need to manually force the autoload before monkey patching. You can do this by simply referencing the constant with:

Watir::IE

Simply include this at some point after requiring watir-classic and before monkey patching.

require 'watir-classic'
Watir::IE # this will load the code

module Watir
    class Element
        def generate_ruby_code(element, method_name, *args)
            puts "Print this"
        end
    end
end

browser = Watir::Browser.new
browser.goto 'www.google.ca'
browser.link.click_no_wait
#=> "Print this"

OTHER TIPS

Look, I do not know what exactly is happening in your case, but you can safely rule out Ruby malfunctioning. Here are a couple of hints what you can do:

# Assuming that your element of class Watir::Element is stored in variable x:

x.method( :generate_ruby_code ).owner # will give you the owning module

x.method( :generate_ruby_code ).source_location # will give you the place where the method is,
# that is going to be used when you send x the message :generate_ruby_code

x.class # will confirm that your object indeed is what you think it is

x.singleton_class.ancestors # will give you the full method lookup chain for x

With this, you shoul be equipped to uncover why your expectations for x's behavior are not met.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top