# Mimic File.open pattern

**URL:** <https://www.ruby-forum.com/t/mimic-file-open-pattern/100584>\
**Category:** Ruby\
**Created:** [July 30, 2006, 3:17pm UTC](https://www.ruby-forum.com/t/mimic-file-open-pattern/100584 "2006-07-30T15:17:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![SchSSS\_le\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a183cd/32.png) [@SchSSS\_le\_Daniel](https://www.ruby-forum.com/u/SchSSS_le_Daniel)\
**Post date:** [July 30, 2006, 3:17pm UTC](https://www.ruby-forum.com/t/mimic-file-open-pattern/100584/1 "2006-07-30T15:17:08Z")

</div>

Hello all,

open is singleton method of File and can be used in two ways

# 1 way

f = File.open(“data”)  
f.readline until f.lineno == 10  
puts f.readline  
f.close

# 2 way

File.open(“data”) do |f|  
f.readline until f.lineno == 10  
puts f.readline  
end

I am trying to mimic this with my own classes

irb(main):001:0\> class Resource  
irb(main):002:1\> @@cnt=0  
irb(main):003:1\> def initialize  
irb(main):004:2\> @id = @@cnt  
irb(main):005:2\> @@cnt += 1  
irb(main):006:2\> end  
irb(main):007:1\> def id;@id;end  
irb(main):008:1\> end  
=\> nil  
irb(main):009:0\> class Q  
irb(main):010:1\> def Q.get &block  
irb(main):011:2\> r = Resource.new  
irb(main):012:2\> if Kernel::block\_given?  
irb(main):013:3\> block.call®  
irb(main):014:3\> else  
irb(main):015:3\* return r  
irb(main):016:3\> end  
irb(main):017:2\> end  
irb(main):018:1\> end  
=\> nil  
irb(main):019:0\> Q.get  
=\> #\<Resource:0x40206fe0 @id=0\>  
irb(main):020:0\> Q.get {|r| puts r.id}  
1  
=\> nil  
irb(main):021:0\>

I am interested in further suggestions  
is my implementation close to that of File.open?

Regards, Daniel

---

<div class="post-metadata">

**Author:** ![SchSSS\_le\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a183cd/32.png) [@SchSSS\_le\_Daniel](https://www.ruby-forum.com/u/SchSSS_le_Daniel)\
**Post date:** [July 30, 2006, 4:18pm UTC](https://www.ruby-forum.com/t/mimic-file-open-pattern/100584/2 "2006-07-30T16:18:37Z")

</div>

Schüle Daniel wrote:

> # 2 way
> 
> irb(main):004:2\> @id = @@cnt  
> irb(main):014:3\> else  
> irb(main):021:0\>
> 
> I am interested in further suggestions  
> is my implementation close to that of File.open?

You’re missing the cleanup part when called with a block. The crucial  
bit is that the block form allows proper cleanup under all circumstances  
by using begin - ensure.

Kind regards

```
robert
```

---

<div class="post-metadata">

**Author:** ![SchSSS\_le\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a183cd/32.png) [@SchSSS\_le\_Daniel](https://www.ruby-forum.com/u/SchSSS_le_Daniel)\
**Post date:** [July 30, 2006, 4:18pm UTC](https://www.ruby-forum.com/t/mimic-file-open-pattern/100584/3 "2006-07-30T16:18:48Z")

</div>

Schüle Daniel wrote:

> # 2 way
> 
> irb(main):004:2\> @id = @@cnt  
> irb(main):014:3\> else  
> irb(main):021:0\>  
> First off, you can make it more efficient if your use `yield’ instead of  
> calling the block explicitly:

class Q  
def self.get  
if block\_given?  
yield Resource.new  
else  
Resource.new  
end  
end  
end

The above is what I’d go with, but there a lots of ways to accomplish  
what you want. Take this for example:

class Q  
def self.get  
yield resource = Resource.new  
rescue LocalJumpError  
resource  
end  
end

or even shorter (though it’ll catch other exceptions as well, so you  
have to be careful)

class Q  
def self.get  
yield(resource = Resource.new) rescue resource  
end  
end

Cheers,  
Daniel

---

<div class="post-metadata">

**Author:** ![SchSSS\_le\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a183cd/32.png) [@SchSSS\_le\_Daniel](https://www.ruby-forum.com/u/SchSSS_le_Daniel)\
**Post date:** [July 30, 2006, 10:20pm UTC](https://www.ruby-forum.com/t/mimic-file-open-pattern/100584/4 "2006-07-30T22:20:24Z")

</div>

Daniel S. wrote:

> > irb(main):003:1\> def initialize  
> > irb(main):013:3\> block.call(r)  
> > =\> nil  
> > Resource.new  
> > rescue LocalJumpError  
> > end  
> > end
> 
> Cheers,  
> Daniel

There’s no need to golf this. There’s a well-known idiom for coding  
block-scoped resources. See the section entitled “Destroy this object  
when it goes out of scope” at  
[http://wiki.rubygarden.org/Ruby/page/show/RubyIdioms](http://wiki.rubygarden.org/Ruby/page/show/RubyIdioms). Here’s the example  
from that page:

def Resource.open( identifier ) # :yield: resource  
resource = Resource.new( identifier )  
if block\_given?  
begin  
yield resource  
ensure  
resource.close  
end  
else  
return resource  
end  
end

The benefit of using the standard idiom is that any Ruby programmer that  
reads your code will instantly understand what it’s doing. Coding it any  
other way will likely cause a bit of confusion. And, of course, if you  
don’t use the idiom you might forget the “ensure” part.

---

<div class="post-metadata">

**Author:** ![SchSSS\_le\_Daniel](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/a183cd/32.png) [@SchSSS\_le\_Daniel](https://www.ruby-forum.com/u/SchSSS_le_Daniel)\
**Post date:** [July 30, 2006, 11:07pm UTC](https://www.ruby-forum.com/t/mimic-file-open-pattern/100584/5 "2006-07-30T23:07:30Z")

</div>

Timothy H. wrote:

> > > f.close  
> > > irb(main):002:1\> @@cnt=0  
> > > irb(main):012:2\> if Kernel::block\_given?  
> > > 1  
> > > else  
> > > yield resource = Resource.new  
> > > yield(resource = Resource.new) rescue resource  
> > > [http://wiki.rubygarden.org/Ruby/page/show/RubyIdioms](http://wiki.rubygarden.org/Ruby/page/show/RubyIdioms). Here’s the example  
> > > else  
> > > return resource  
> > > end  
> > > end
> 
> The benefit of using the standard idiom is that any Ruby programmer that  
> reads your code will instantly understand what it’s doing. Coding it any  
> other way will likely cause a bit of confusion. And, of course, if you  
> don’t use the idiom you might forget the “ensure” part.

I don’t think the original post mentioned that the resource needed to be  
closed 🙂 I thought he wanted an easy way to either yield or return. But  
yes, for that wider problem, your code is superior. We were just  
answering different questions.

Cheers,  
Daniel
