Reputation: 862
I'm trying to extend the File
class inside a module. Here's my (abbreviated) code:
module Wireshark
# Extend the file class to write a header comment
class File
def write_header
self.puts '/* ' + Wireshark::AUTOGEN_LABEL + ' */'
self.puts '/* ' + Wireshark::timestamp + ' */'
end
end
# Read a file
def read
begin
file = File.read 'file'
rescue IOError
STDERR.puts 'Error reading file.'
return
end
end
end
When I run my code, I'm getting
undefined method `read' for Wireshark::File:Class (NoMethodError)
when I try to run file.read
. I tried getting rid of the module encapsulation, but I'd like to only extend the File
class inside my module, not in the rest of my program.
Upvotes: 1
Views: 105
Reputation: 62638
You're close.
module Wireshark
module File
def write_header
self.puts '/* ' + Wireshark::AUTOGEN_LABEL + ' */'
self.puts '/* ' + Wireshark::timestamp + ' */'
end
end
# Extend File with the methods in the Wireshark::File module
::File.send :include, Wireshark::File
# Read a file
def read
begin
file = ::File.read 'file'
rescue IOError
STDERR.puts 'Error reading file.'
return
end
end
end
The general idea here is that we define a Wireshark::File
module that holds the methods you want to include on the File
class, then you can just include them on File directly.
You'll also notice that in the read
method, I changed File
to ::File
. Ruby will walk up the tree to try to find the nearest matching value for a given constant, so since you are in the Wireshark
module, and there is a constant named File
in that scope, using just File
gets you Wireshark::File
. Specifying ::File
means "The File
constant at the top-level namespace".
Upvotes: 1
Reputation: 211560
In the current version of Ruby it's not possible to do this, but it is a popular proposed extension called "refinements".
If you need to patch the core File
class, you'll need to do that as a monkey patch, and this affects all instances of File
anywhere in your Ruby process.
Normally you can do it this way:
# Define the instance methods you want to overide
module MyFileHacksInstanceMethods
def read
# ... (reimplementation) ...
end
end
# Force load these in the File class
class File
include MyFileHacksInstanceMethods
end
What you've declared in your example here is an independent class called Wireshark::File
because it's within that module's namespace. ::File
is the main class (::
being a prefix to force absolute name, sort of like /
for filesystems).
Upvotes: 0