开发者

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=-rubygems

Test 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜