# Ruby syntax question: instance.method(args) { more\_stuff }

**URL:** <https://www.ruby-forum.com/t/ruby-syntax-question-instance-method-args-more-stuff/103067>\
**Category:** Ruby\
**Created:** [May 1, 2007, 12:15pm UTC](https://www.ruby-forum.com/t/ruby-syntax-question-instance-method-args-more-stuff/103067 "2007-05-01T12:15:47Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nic\_D](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/839c29/32.png) [@Nic\_D](https://www.ruby-forum.com/u/Nic_D)\
**Post date:** [May 1, 2007, 12:15pm UTC](https://www.ruby-forum.com/t/ruby-syntax-question-instance-method-args-more-stuff/103067/1 "2007-05-01T12:15:47Z")

</div>

Hi, I’m having difficulty working out the following construct:  
img.write(“myimage.jpg”) { self.quality = 50 }  
In this example (source  
[RMagick 1.15.0: Common Tasks](http://www.simplesystems.org/RMagick/doc/comtasks.html)), img is a  
RMagick::Image.

The API says “You may also specify optional arguments by setting  
Image::Info [http://www.simplesystems.org/RMagick/doc/info.html](http://www.simplesystems.org/RMagick/doc/info.html)  
attributes in an associated block.” Is this a standard syntax in Ruby or  
is it specific to this write method? And how does it work, how can I  
make my own method accept blocks too? any advantage over passing a array  
of arguments?

Also, I’m trying to pass my own instance variable in order to replace  
the sample value of 50. So I’ve tried:

img.write(“myimage.jpg”) { self.quality = @my\_object\_quality }

Where @my\_object\_quality is defined as an instance variable on my class  
def. But the interpreters seams to look for a @my\_object\_quality  
instance variable _within_ the RMagick class, which vaguely kind of make  
sense. So how can I pass this instance variable into this method? and  
why does it say “self.quality = 50” in the example and not “@quality =  
50”?

Thanks in adance for your help. I’m looking for a genuine explanation of  
what’s happening at a Ruby syntax level, not just a code sample that  
would work with this RMagick example.

Nic

---

<div class="post-metadata">

**Author:** ![Nic\_D](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/839c29/32.png) [@Nic\_D](https://www.ruby-forum.com/u/Nic_D)\
**Post date:** [May 1, 2007, 12:26pm UTC](https://www.ruby-forum.com/t/ruby-syntax-question-instance-method-args-more-stuff/103067/2 "2007-05-01T12:26:47Z")

</div>

On 5/1/07, Nic D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> how can I  
> make my own method accept blocks too?

Here is one explanation.

[http://www.rubycentral.com/book/tut\_containers.html#UD](http://www.rubycentral.com/book/tut_containers.html#UD)

Harry

---

<div class="post-metadata">

**Author:** ![Nic\_D](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/839c29/32.png) [@Nic\_D](https://www.ruby-forum.com/u/Nic_D)\
**Post date:** [May 1, 2007, 1:05pm UTC](https://www.ruby-forum.com/t/ruby-syntax-question-instance-method-args-more-stuff/103067/3 "2007-05-01T13:05:50Z")

</div>

On Tue, May 01, 2007 at 07:14:43PM +0900, Nic D. wrote:

> The API says “You may also specify optional arguments by setting  
> Image::Info [http://www.simplesystems.org/RMagick/doc/info.html](http://www.simplesystems.org/RMagick/doc/info.html)  
> attributes in an associated block.” Is this a standard syntax in Ruby or  
> is it specific to this write method? And how does it work, how can I  
> make my own method accept blocks too? any advantage over passing a array  
> of arguments?

It’s fairly standard. It has the advantage of only being run when  
required,  
e.g. zero times if no object ends up being created, or it could be run  
multiple times. Compare:

```
a = Array.new(2) { [] }
a[0] << 'bar'
a[1] << 'bap'

```

Here the initialization block is run twice, so you get two different  
empty  
arrays. This is different to

```
a = Array.new(2, [])
a[0] << 'bar'
a[1] << 'bap'

```

Try it in irb, and look at ‘a’ afterwards in both cases.

For another example of this pattern, look at dependency injection, e.g.  
[http://wikis.onestepback.org/OSB/page/show/DependencyInjectionCode/DepInjRb](http://wikis.onestepback.org/OSB/page/show/DependencyInjectionCode/DepInjRb)  
(site appears to be very slow at present)

In this case the advantage is that the initialization code is run at the  
latest possible time; at the time the block is created not all the  
values  
are known.

How to do it yourself?

class Foo  
attr\_accessor :x  
def initialize(&blk)  
instance\_eval(&blk) if blk  
end  
end  
a = Foo.new { self.x = 99 }  
puts a.x

> Also, I’m trying to pass my own instance variable in order to replace  
> the sample value of 50. So I’ve tried:
> 
> img.write(“myimage.jpg”) { self.quality = @my\_object\_quality }
> 
> Where @my\_object\_quality is defined as an instance variable on my class  
> def. But the interpreters seams to look for a @my\_object\_quality  
> instance variable _within_ the RMagick class, which vaguely kind of make  
> sense. So how can I pass this instance variable into this method?

Simplest just to use a local variable:

foo = @my\_object\_quality  
… { self.quality = foo }

If there are lots of these, then pass an instance of yourself, as long  
as  
you have public accessor methods.

template = self  
… { self.quality = template.quality }

> and  
> why does it say “self.quality = 50” in the example and not “@quality =  
> 50”?

I guess it’s just standard accessor syntax, where it’s considered  
cleaner to  
call a setter method (which might implement additional logic) rather  
than  
twiddle directly with instance variables in an object, which are usually  
considered ‘private’

Brian.

---

<div class="post-metadata">

**Author:** ![Nic\_D](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/839c29/32.png) [@Nic\_D](https://www.ruby-forum.com/u/Nic_D)\
**Post date:** [May 1, 2007, 2:42pm UTC](https://www.ruby-forum.com/t/ruby-syntax-question-instance-method-args-more-stuff/103067/4 "2007-05-01T14:42:28Z")

</div>

Brian C. wrote:

> On Tue, May 01, 2007 at 07:14:43PM +0900, Nic D. wrote:  
> (…)
> 
> > why does it say “self.quality = 50” in the example and not “@quality =  
> > 50”?
> 
> I guess it’s just standard accessor syntax, where it’s considered  
> cleaner to  
> call a setter method (which might implement additional logic) rather  
> than  
> twiddle directly with instance variables in an object, which are usually  
> considered ‘private’
> 
> Brian.

Brian’s explanation is correct. I learned this technique from the 1st  
edition of Hal F.'s “The Ruby Way.” I think I remember seeing it in  
the 2nd edition, too, although I don’t have my copy with me to check.

I’m using this technique to support the dozen or so optional arguments  
that Image#write can accept. Overall it works well, although since the  
block is executed in the context of an RMagick object, all that object’s  
instance variables are exposed to the caller. RMagick mitigates this  
problem by running the block in the context of an Image::Info object,  
which doesn’t have any private data or methods, just attribute  
accessors.
