Use of call method with a block

I am new to ruby and was trying to figure how the block will be executed
in a particular case.

class Test

def A ( &old_block)
unbound_obj = instance_method(:B)
define_method(:B) do |*args, &block|
instance_exec(*args,&old_block)
unbound_obj.bind(self).call(*args,&block)
end

def B(*args, &block)

end

end

Query:

  1. Is Instance_exec in A going to form the body of method B or it will
    simply execute the old_block and perform the action whatever were
    present in old block

  2. Can call take block as arguments, if yes, then when this block will
    be executed, considering that method B has some body as well.

Thanks

Where did you take this code snippet from?

In Ruby, methods are usually defined with lowercase.

At the time the interpreter reach this line:
“unbound_obj = instance_method(:B)”
the method B does not exist, this will throw an error (Ruby is not
compiled, it has no forward declaration).

You did not give the #instance_exec a receiver (like k.instance_exec…)
so it will be executed on ‘main’ and not on an instance of Test.

Anyway if you define a method in a class (whatever you used to define
it), and later redefine that method, the previous functionality will be
lost.

“Method name in caps” :frowning:

Thanks for pointing out, I am from old school of programming and new to
ruby.

However the intent was not to seek correction of syntax but understand
the usage of block and define_method

Let me rephrase the question with proper working code snippet

module Trial
class Test
def self.methodA (method_name, &block)
method_name = method_name.to_sym

  define_method(method_name, &block)

  un_obj = instance_method(method_name)

  define_method(method_name) do |*args, &new_block|
    un_obj.bind(self).call(*args, &new_block)
  end
end

end
end

Trial::Test.methodA(“b”) {puts “Help I am in A” }
obj = Trial::Test.new
obj.b do
puts “Hello World”
end

Output:
Help I am in A

Question: 1. The block passed in call Obj.b is lost and no error is
reported. Why ?

If I call methodA like below
Test.methodA(“b”) {… ; yeild}

To execute a block with “obj.b” first declaration must have yeild
statement, however placing yeild in block give error.
Why?

Thanks in advance
Rakesh

The block in obj.b is not lost, it is simply not invoked.

This:

define_method(method_name, &block)

creates a new method ‘b’ with the code:

{puts “Help I am in A” } #(through calling the class method)

Then you create a reference to this method (not just to the name #b, but
the entire method, along with its variables and functionality at the
moment you created that reference):

un_obj = instance_method(method_name)

(from this point on, you could even delete or completely rewrite method
‘b’, un_obj will still work, printing “Help I am in A”)

Then you create a new method, with the same name as the previous (why?),
and inside that method you execute the old method (un_obj), so it will
still print “Help I am in A”. The old method does not care if you pass
arguments and a block to it, as its signature (the old method) did not
contain any arguments.

Thanks. Now I am able to understand where I was loosing the context.

“Then you create a new method, with the same name as the previous
(why?)”

–> I have no answer to this, I am also trying to figure this out.
The code in class Test is meant to build the code which in turn will
process the DSL for sure.

Building the code like –

methodA B do


yeild/blk.call
end

Which explains the role of first define_method call

On DSL I am expecting something like … but unable to find in existing
code

B do |x,y|

– Do something
end

Rakesh Gulati wrote in post #1179134:

–> I have no answer to this, I am also trying to figure this out.
??
Does this mean you did not write this code? (and you just want to
understand it?)

It would be much better if you’d wrote what you want to accomplish, that
way a lot more people could help you.