1

What I want to do is define a method that gets the result of every method in a block (or calls every method in a block) and returns the resultant string...

For example:

def a_method(&block)
    ## build a string by calling each of the blocks methods
end

def brackets(str)
    '('+str+')'
end

a_method do
    brackets "foo"
    brackets "bar"
end

# desired output => (foo)(bar)

I tried putting yield in a_method, but as I expected that just returns the last evaluated expression from the block (in this case, (bar)).

I've looked around on how to build a string from calls inside a block, but can't find anything. I would have thought this would be quite a common technique.. could someone explain how?

3 Answers 3

2

You can use a DSL object to handle this, giving you more flexibility:

class StringBuilder
  def method_missing(method, *args, &block)
    @strings << (@original_self.send method, *args, &block)
  end

  def build(&block)
    @strings = []
    @original_self = eval "self", block.binding
    instance_eval &block
    @strings.join(' ') #format as you like
  end
end

Now use where needed:

sb = StringBuilder.new
sb.build do
  brackets "foo"
  brackets "bar"
end
#=> (foo) (bar)
Sign up to request clarification or add additional context in comments.

1 Comment

Just a caveat: because this relies on method_missing, in the unlikely event you try to build strings using methods already included in the Object class this won't work properly. You can have the StringBuilder inherit from BlankSlate to get around this if need be.
0
["foo", "bar"].map(&method(:brackets)).join

UPDATE Another way if you want to use various methods:

def a_method(&block)
    ## build a string by calling each of the blocks methods
    p block[].join
end

def brackets(str)
    '('+str+')'
end

a_method do
    [ brackets("foo"),
      brackets("bar") ]
end

2 Comments

thanks, but the question isn't really about the output, it's about specifically using block syntax.
I've seen code that does it without putting it in a list.. because yes my goal is to use multiple methods
0

If you stricly want to use blocks to create your string, you will have to use clever ways to remember it. One of those ways is to use a string instance and eval the block on it.

def a_method(&block)
  "".instance_eval(&block)
end

def brackets(str)
  self << "(#{str})"
end

str = a_method do
  brackets "foo"
  brackets "bar"
end

puts str
#=> (foo)(bar)

3 Comments

hmm.. could I somehow respond to method calls from the block in the method that handles the block? (a_method) - what I'm trying to achieve is HTML-generation using blocks as demonstrated on tryruby.org
looks like you're onto the right thing with instance_eval.... github.com/Sophrinix/TryRuby/blob/…
I was typing up but you can just refer to PinnyM's answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.