On Tue, May 01, 2007 at 07:14:43PM +0900, Nic Daniau wrote:
> The API says "You may also specify optional arguments by setting
> Image::Info <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
(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.