Pass a method that receives args to another method that takes a block

256 Views Asked by At

I have some code that needs to be called directly or passed to another method that must take a block. Pseudocode:

class Foo
  def bar
    if condition
      return method_that_needs_a_block!('string', named1:, named2:) do
        shared_method('a', 'b')
      end
    end

    shared_method('a', 'b')
  end

  def shared_method(arg1, arg2)
    puts arg1
    puts arg2
  end

end

You can see the method that must take a block method_that_needs_a_block has a string for the first parameter and the rest are named parameters. How can shared_method be used as either a method or a block and still be able to pass the arguments to it? I've attempted making the method a lambda but I'm still unsure how to use it within the block context.

1

There are 1 best solutions below

1
On

I'm not sure I 100% understand the question but if you want to pass a method as a block use &method(:method_name).

class Foo
  def bar(a, b, &block)
    if block_given?
      TheGemToEndAllGems.frobnobize(a, b, &block)
    else
      TheGemToEndAllGems.frobnobize(a, b, &method(:default_method))
    end
  end

  def default_method(a, b)
    puts "default method says: #{a} #{b}"
  end
end
module TheGemToEndAllGems
  def self.frobnobize(a, b)
    yield a, b if block_given?
  end
end 
irb(main):090:0> Foo.new.bar('Hello', 'World')
default method says: Hello World

Since parens are optional in Ruby there is a special method method which is used to get refences to methods - it returns a Method object. This is somewhat like a function reference in other languages.

Since blocks in Ruby are not actually objects and passed differently the & operator is used to turn the method object into a Proc.