Ruby: How to Pass All Parameters and Blocks Received by One Method to Another

Ruby: How do I pass all parameters and blocks received by one method to another?

You can use * and & in method calls to turn arrays back into lists of arguments and procs back into blocks. So you can just do this:

def myhelper(*args, &block)
link_to(*args, &block)
# your code
end

Passing block from one method to another

Short answer: Always use yield, unless you have a good reason to explicitly reference &block.

See: Why blocks make ruby methods 439% slower

With &block, you get a reified Proc on which you can do all kinds of stuff and which you can move around. However, with a yield and an implicit block, you are limited to only calling the block.

By using yield, the interpreter can bypass all the Proc reification as it knows the developer won't be able to use it; hence it can keep just a C-level structure instead of having to set up a Ruby-level object.

Why can't we pass a {} block with other parameters to a method in Ruby

You can only pass other objects as arguments, and blocks are not objects in Ruby. Blocks are syntactic constructs.

But they can easily be wrapped in objects, objects of Proc class. There is even a special shorthand operator for that:

method4(true, 4, &->{puts 'Hello World'})

A short explanation of above code:

->{} creates a Proc object around given block. As method4 requires a block, and not an object, you need to "unwrap" it to block once more, and that's why ampersand is there. If the signature of method4 were instead:

def method4(condition, attribute, proc) # note no ampersand

you would be able to omit the ampersand in method call too.

Pass block passed to method to another method in Ruby

You can reference the block explicitly

def discard(&block)
self - self.keep(&block)
end

or implicitly

def discard
self - self.keep(&Proc.new {})
end

In your case, I would suggest the first approach.

How can I automatically forward all paramters from one method to another in Ruby?

I know one appriximate method:

def method_a *args
# do some stuff
method_b *args
end

def method_b *args
# do other stuff
end

or expanding arguments in the second method:

def method_a *args
# do some stuff
method_b *args
end

def method_b p1, p2
# do other stuff
end

Since super is key-work method, the ruby interperter can treat it as of the same argument list as in the specific method you've called. But default from to call a method without argument is the same as for super method, just method name:

method_a # calls to :method_a without arguments, not as the same argument list for the caller method.

So, it will be strong omonim for the call method syntax.

How to pass a block to another in Ruby?

You can't use yield in a. Rather, you have to pass a Proc object. This would be the new code:

def do_something(a,&b)
AnotherClass.instance_exec(b, &a)
end

a = Proc.new do |b|
puts "start"
b.call
puts "end"
end

do_something(a) do
puts "this block is b!"
end

yield is only for methods. In this new code, I used instance_exec (new in Ruby 1.9) which allows you to pass parameters to the block. Because of that, we can pass the Proc object b as a parameter to a, which can call it with Proc#call().

Pass method name as parameter to another method

You want to use send:

def two(param, callback)
send(callback, param)
end

How to pass blocks between methods?

You could just pass the &block to your second method like so:

def one(&block)
two(&block)
end

def two(&block)
block.call
end

one { puts "Hello World" }
Hello World
#=> nil

Update

You could also do something like this

def one
two(&Proc.new)
end

def two(&block)
block.call
end

It will have the same output as above. Do note that if no block is given to one, it will raise an ArgumentError: tried to create Proc object without a block so you'd have to check if the block is given by calling if block_given?



Related Topics



Leave a reply



Submit