Hi --

On Wed, 4 Jul 2007, Ivan Vega wrote:

> Hi,
>
> I'm trying something very simple, like passing a method a string, and
> two more strings to surround that with... i.e.:
>
> around_string('mystring') {|b, a| b = 'before'; a = 'after';}
>
> The method:
>
> def around_string(string, &block)
>    b, a = yield
>    "#{b}#{string}#{a}"
> end
>
> That of course doesn't work because I still don't get how blocks and
> procs work and what they are. The reason I don't just pass 'a' and 'b'
> as parameters to the method is because the method has other parameters I
> don't want to touch, and it seemed like a block as the last parameter
> would be a good choice (I simplified my example so it's clearer).
>
> So I wanted to know what's the best way to accomplish what I'm trying to
> do...
>
> Thanks for your patience :)

The way a code block works, basically, is that it hangs off the right
of the method call (as you've got it); it contains code; and the
method has the ability to execute that code, using yield.  The value
returned from the block, using standard Ruby statement/expression
evaluation, is the value of the yield statement itself.

Thus:

   def my_method
     x = yield
     puts "I got back #{x}"
   end

   my_method { 10 }          # I got back 10
   my_method { "a string" }  # I got back a string

In your case, you would want:

   def around_string(string)
     b,a = yield
     "#{b}#{string}#{a}"
   end

   around_string("abc") { ["before", "after"] }   # beforeabcafter

Note that all the block has to do is provide a value.  You *can* pass
arguments to a block -- but in this case there's not much point, since
all that the method actually needs is two strings (which I've packed
up in an array).

Also, note that you don't need &block.  &block is a special parameter
syntax that takes the code block and turns it into a Proc object.  You
need that if you're planning to pass the block around as an object, or
call another method using the same block; but if all you need to do is
yield, you can just do it.


David

P.S. You could also write your method as:

   def around_string(string)
     yield.join(string)
   end

but that's just for fun :-)

-- 
* Books:
   RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
   RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
     & consulting:  Ruby Power and Light, LLC (http://www.rubypal.com)