How can a code block access an object's variables?

J

Jacob Rubynovice

Dear Rubyists,

I am a novice Ruby developer who is interested in figuring out a way to
design something like what is demonstrated below. The reason why
each_line would not work in this example is because when you pass a
block of code to the FileReader object, the memory (members of
FileReader) is not shared with the block of code that is sent to
FileReader.

Maybe I have the wrong idea for how this would be designed. I just
think it would be very convenient to do this sort of thing because I
could re-use the code to open a file and read lines and only pass it
code blocks pertainant to what I want to do with those lines of code.

Please note that I do not only want to do this for an open file/read
line script. It would also be useful if you were expanding an IP range
that exceeds what you could store into an array object because you could
write an each_host method that takes in a block of code that relates to
what you want to do to each host.

class FileReader

def initialize(fname, &block)
@filename = fname
end
def each_line(&block)
begin
source = File.new(@filename, "r")
rescue => err
exit
end
begin
while(line = source.readline)

line.strip!
if((line == "") || (line =~ /[\t+\s+]/))
next
end
block.call
end
rescue EOFError
source.close
rescue => err
puts "[!] #{err}"
exit
end
end

end
my_reader = FileReader.new(ARGV[0])
my_reader.each_line { puts line
# do more parsing stuff here
}
 
R

Rick DeNatale

Dear Rubyists,

I am a novice Ruby developer who is interested in figuring out a way to
design something like what is demonstrated below. The reason why
each_line would not work in this example is because when you pass a
block of code to the FileReader object, the memory (members of
FileReader) is not shared with the block of code that is sent to
FileReader.

Maybe I have the wrong idea for how this would be designed. I just
think it would be very convenient to do this sort of thing because I
could re-use the code to open a file and read lines and only pass it
code blocks pertainant to what I want to do with those lines of code.

Please note that I do not only want to do this for an open file/read
line script. It would also be useful if you were expanding an IP range
that exceeds what you could store into an array object because you could
write an each_host method that takes in a block of code that relates to
what you want to do to each host.

class FileReader

def initialize(fname, &block)
@filename = fname
end
def each_line(&block)
begin
source = File.new(@filename, "r")
rescue => err
exit
end
begin
while(line = source.readline)

line.strip!
if((line == "") || (line =~ /[\t+\s+]/))
next
end
block.call
end
rescue EOFError
source.close
rescue => err
puts "[!] #{err}"
exit
end
end


This can be made much shorter using Ruby conventions:

class FileReader

def initialize(fname, &block)
@filename = fname
end

def each_line
source = File.open(@filename, "r") do |f| # this will
automatically close the file
f.each do | line | # This avoids having to check for
end-of-file explicitly.
line.strip!
yield line unless ((line == "") || (line =~ /[\t+\s+]/))
end
end
rescue => err # Note that a method definition itself acts like begin/end
puts "[!] #{err}"
exit
end
end

The two inner lines:
line.strip!
yield line unless ((line == "") || (line =~ /[\t+\s+]/))

could be combined as:

yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))

But I think that the two line form might be a little clearer.

I'm not sure just what you expect the regex to be doing, as you've
coded it it's going to skip any line which
has at least one tab followed immediately by at least one whitespace
character regardless of anything else in the line.
 
R

Robert Klemme

Dear Rubyists,

I am a novice Ruby developer who is interested in figuring out a way to
design something like what is demonstrated below. The reason why
each_line would not work in this example is because when you pass a
block of code to the FileReader object, the memory (members of
FileReader) is not shared with the block of code that is sent to
FileReader.

Maybe I have the wrong idea for how this would be designed. I just
think it would be very convenient to do this sort of thing because I
could re-use the code to open a file and read lines and only pass it
code blocks pertainant to what I want to do with those lines of code.

Please note that I do not only want to do this for an open file/read
line script. It would also be useful if you were expanding an IP range
that exceeds what you could store into an array object because you could
write an each_host method that takes in a block of code that relates to
what you want to do to each host.

class FileReader

def initialize(fname, &block)
@filename = fname
end
def each_line(&block)
begin
source = File.new(@filename, "r")
rescue => err
exit
end
begin
while(line = source.readline)

line.strip!
if((line == "") || (line =~ /[\t+\s+]/))
next
end
block.call
end
rescue EOFError
source.close
rescue => err
puts "[!] #{err}"
exit
end
end


This can be made much shorter using Ruby conventions:

class FileReader

def initialize(fname, &block)
@filename = fname
end

def each_line
source = File.open(@filename, "r") do |f| # this will
automatically close the file
f.each do | line | # This avoids having to check for
end-of-file explicitly.
line.strip!
yield line unless ((line == "") || (line =~ /[\t+\s+]/))
end
end
rescue => err # Note that a method definition itself acts like begin/end
puts "[!] #{err}"
exit
end
end

The two inner lines:
line.strip!
yield line unless ((line == "") || (line =~ /[\t+\s+]/))

could be combined as:

yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))

But I think that the two line form might be a little clearer.

I'm not sure just what you expect the regex to be doing, as you've
coded it it's going to skip any line which
has at least one tab followed immediately by at least one whitespace
character regardless of anything else in the line.

No, the complete expression will skip empty lines as well we lines that
contain either a tab, a space (which includes tab IIRC) or a plus sign.

irb(main):004:0> /[\t+\s+]/ =~ " "
=> 0
irb(main):005:0> /[\t+\s+]/ =~ "+"
=> 0
irb(main):007:0> /\s/ =~ "\t"
=> 0

Even shorter

File.foreach file do |line|
next if /^\s*$/ =~ line
line.chomp!
# whatever
end

You can even stick this into a method, e.g.

def File.each_non_empty file
foreach file do |line|
next if /^\s*$/ =~ line
line.strip!
yield line
end
end

Note that the regular expression that was posted originally is most
likely wrong.

Kind regards

robert
 
R

Ruby Novice

Robert said:
Maybe I have the wrong idea for how this would be designed. I just
class FileReader
begin
rescue => err
def initialize(fname, &block)
end

could be combined as:

yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))

But I think that the two line form might be a little clearer.

I'm not sure just what you expect the regex to be doing, as you've
coded it it's going to skip any line which
has at least one tab followed immediately by at least one whitespace
character regardless of anything else in the line.

No, the complete expression will skip empty lines as well we lines that
contain either a tab, a space (which includes tab IIRC) or a plus sign.

irb(main):004:0> /[\t+\s+]/ =~ " "
=> 0
irb(main):005:0> /[\t+\s+]/ =~ "+"
=> 0
irb(main):007:0> /\s/ =~ "\t"
=> 0

Even shorter

File.foreach file do |line|
next if /^\s*$/ =~ line
line.chomp!
# whatever
end

You can even stick this into a method, e.g.

def File.each_non_empty file
foreach file do |line|
next if /^\s*$/ =~ line
line.strip!
yield line
end
end

Note that the regular expression that was posted originally is most
likely wrong.

Kind regards

robert

You are correct. I was wrong with that regular expression. I was
trying to make a regular expression that ignores lines that only contain
white space- tabs, spaces, newlines (although newlines/returns are
automatically removed with the strip method).

Additionally, I just want to thank all of you for your suggestions.
They have been tremendously helpful. I think that the code block
feature of Ruby can be used to save tons of re-coding that would
otherwise need to be done in most of the modern conventional programming
languages.
 
R

Rick DeNatale

On 29.05.2008 19:04, Rick DeNatale wrote:
yield line unless ((line.strip! == "") || (line =~ /[\t+\s+]/))

But I think that the two line form might be a little clearer.

I'm not sure just what you expect the regex to be doing, as you've
coded it it's going to skip any line which
has at least one tab followed immediately by at least one whitespace
character regardless of anything else in the line.

No, the complete expression will skip empty lines as well we lines that
contain either a tab, a space (which includes tab IIRC) or a plus sign.

Right you are, for some reason I failed to see the square brackets.
Maybe I DO need new glasses. <G>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,056
Latest member
GlycogenSupporthealth

Latest Threads

Top