1

I have a method

def method1(&block)
  #.............
  if condition == "yes"
    yield if block_given?
    {success: :true, value: **value returned from the block**}
  else        
    {is_success: :false, value: get_errors_array() }
  end
end

How do retrieve the value from &block? Should the &block use return keyword for that?

0

4 Answers 4

6

Nope, there shouldn't be a return in a block here. The "return" value of block is the value of last expression in it.

value_returned = yield if block_given?

Sign up to request clarification or add additional context in comments.

4 Comments

If I want a &block to be given always, how do I achieve that?
Well, I guess you have to throw exception when block_given? returns false.
What if just call it as value_returned = yield
If calling it without checking and no block given, there will be an error.
3
def method1
  fail("Needs block") unless block_given?
  if condition
    {success: true, value: yield}
  else        
    {success: false, value: get_errors_array}
  end
end

Notes and questions:

  • If you use yield is not idiomatic to put &block in the method arguments. If you want to require the block write fail("Need blocks") unless block_given?. You can leave it out and then you'll get a "LocalJumpError: no block given", which is also ok.
  • yield is an expression, not an statement.
  • It's not idiomatic to write method().
  • You need a default value to be used when no block is given (unless you fail before, of course).
  • You used different keys success and is_success, why?
  • You used :true and :false instead of real booleans, why?

1 Comment

the expression value_returned = yield will fail anyway if block not given. I need the block to be given always, that's why I don't a default value.
2

Use call.

block.call

if block takes arguments, then give arguments:

block.call(whatever_arguments)

4 Comments

Thanks. How do I make &block require as an argument then?
I don't understand, why has the OP to change (the more idiomatic) yield with block.call?
@tokland It can go either way. Since the OP used the variable block in the argument, I thought call should be used. But the fact that OP used block_given? is contradictory, and it suggests using yield. One way or the other but not both.
indeed, &block goes with block.call and no &block goes with block_given? and yield. Anyway, the problem seems to be that the OP believes yield is an statement.
-1

The & prefix operator will allow a method to capture a passed block as a named parameter.

def wrap &b
     print "dog barks: "
     3.times(&b)
     print "\t"
end
wrap { print "Wow! " }  # Wow!  Wow!  wow!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.