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

**URL:** <https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978>\
**Category:** Ruby\
**Created:** [May 29, 2008, 5:30pm UTC](https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978 "2008-05-29T17:30:55Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![rubynut](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/8e8cbc/32.png) [@rubynut](https://www.ruby-forum.com/u/rubynut)\
**Post date:** [May 29, 2008, 5:30pm UTC](https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978/1 "2008-05-29T17:30:55Z")

</div>

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  
}

---

<div class="post-metadata">

**Author:** ![rubynut](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/8e8cbc/32.png) [@rubynut](https://www.ruby-forum.com/u/rubynut)\
**Post date:** [May 29, 2008, 5:58pm UTC](https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978/2 "2008-05-29T17:58:07Z")

</div>

You can pass arguments to block.call which can then be accessed by the  
block.

block.call(line)

And then when when calling your method, use

```
my_reader.each_line do |myline|
  # myline holds the value of "line"
  puts myline
end

```

There’s a decent introduction to blocks in the Pickaxe book.  
([http://whytheluckystiff.net/ruby/pickaxe/html/tut\_containers.html](http://whytheluckystiff.net/ruby/pickaxe/html/tut_containers.html))

---

<div class="post-metadata">

**Author:** ![rubynut](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/8e8cbc/32.png) [@rubynut](https://www.ruby-forum.com/u/rubynut)\
**Post date:** [May 29, 2008, 7:05pm UTC](https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978/3 "2008-05-29T19:05:22Z")

</div>

On Thu, May 29, 2008 at 11:30 AM, Jacob R. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> think it would be very convenient to do this sort of thing because I
> 
> ```
> while(line = source.readline)
> 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.

–  
Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![rubynut](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/8e8cbc/32.png) [@rubynut](https://www.ruby-forum.com/u/rubynut)\
**Post date:** [May 30, 2008, 5:15pm UTC](https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978/4 "2008-05-30T17:15:45Z")

</div>

Robert K. wrote:

> On 29.05.2008 19:04, Rick DeNatale wrote:
> 
> > > 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.

---

<div class="post-metadata">

**Author:** ![rubynut](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/8e8cbc/32.png) [@rubynut](https://www.ruby-forum.com/u/rubynut)\
**Post date:** [May 30, 2008, 8:02pm UTC](https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978/5 "2008-05-30T20:02:42Z")

</div>

On Thu, May 29, 2008 at 4:29 PM, Robert K.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On 29.05.2008 19:04, Rick DeNatale wrote:

> 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.   
> –  
> Rick DeNatale

My blog on Ruby  
[http://talklikeaduck.denhaven2.com/](http://talklikeaduck.denhaven2.com/)

---

<div class="post-metadata">

**Author:** ![rubynut](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/8e8cbc/32.png) [@rubynut](https://www.ruby-forum.com/u/rubynut)\
**Post date:** [May 29, 2008, 10:30pm UTC](https://www.ruby-forum.com/t/how-can-a-code-block-access-an-objects-variables/138978/6 "2008-05-29T22:30:27Z")

</div>

On 29.05.2008 19:04, Rick DeNatale wrote:

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