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
Ruby on Rails 3 - Public Live Chat
Convert String to Decimal Number in Ruby
Rails: Respond_To JSON and HTML
Check Ruby Http Response for Success
How to Make Sign Up Page Be Root Page in Devise
How to Remove/Disable Sign Up from Devise
Rails: Creating a Custom Data Type/Creating a Shorthand
How to Read Lines from File into Array
Ruby Easy Search for Key-Value Pair in an Array of Hashes
Where/How to Include Helper Methods for Capybara Integration Tests
What's the Most Efficient Way to Deep Copy an Object in Ruby
What Are the Reserved Words Begin or End Used for in Ruby
Ruby on Rails: What Reporting And/Or Charting Tools Are Available