Weird problems with reopening Ruby classes
I'm working simultaneously with Watir and Watir-WebDriver and am trying to make them more compatible by reopening some classes and redefining some methods. I ran into weird behavior that I can't explain开发者_高级运维. I'm trying to understand what's going on.
This is happening with the watir-1.7.1 which is only available on Windows.
Ruby 1.8.7-p330 RUBYOPT=-rubygemsTest 1.
require 'watir'
Watir::ElementCollections.class_eval do
def new_method
end
end
>ruby open-classes-watir1.rb
open-classes-watir1.rb:3: uninitialized constant Watir::ElementCollections (NameError)
Why does Ruby complain about reopening a valid class?
The class in question looks like this:
element_collections.rb:
module Watir
#...
class ElementCollections
include Enumerable
#...
end
end
But that's not all! Now watch this:
Test 2.
require 'watir'
Watir::IE.class_eval do
end
Watir::ElementCollections.class_eval do # Requires the magic incantation above
def new_method
end
end
>ruby open-classes-watir2.rb
It executes fine now with this black magic spell. Watir::IE looks like this:
ie-class.rb:
module Watir
class IE
include WaitHelper
include Exception
include Container
include PageContainer
#...
end
end
Why?
I made a visual aid on this a while back. http://www.flickr.com/photos/marekj/3615299778/ require 'watir' comes from commonwatir gem require 'watir/ie' comes from watir gem. there are two gems at play here.
I suspect the file lib/watir/element_collections.rb
which defines Watir::ElementCollections
is not loaded by calling require 'watir'
. lib/watir/ie.rb
requires lib/watir/core.rb
, which in turn requires lib/watir/element_collections.rb
.
Try this:
require 'watir' require 'watir/core' Watir::ElementCollections.class_eval do def new_method end end
This is happening because require "watir"
doesn't load actually Watir::IE
yet. Watir::IE
is loaded by Kernel.autoload
when doing Watir::Browser.new
. This is how to make it work:
require "watir"
Watir::IE # to trigger autoload
# now Watir::ElementCollections exists
Other solution would be to require "watir/core"
as suggested by Steve.
精彩评论