# Help with passing a callback method

**URL:** <https://www.ruby-forum.com/t/help-with-passing-a-callback-method/109311>\
**Category:** Ruby\
**Created:** [July 13, 2007, 11:25am UTC](https://www.ruby-forum.com/t/help-with-passing-a-callback-method/109311 "2007-07-13T11:25:54Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![micke](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ecae2f/32.png) [@micke](https://www.ruby-forum.com/u/micke)\
**Post date:** [July 13, 2007, 11:25am UTC](https://www.ruby-forum.com/t/help-with-passing-a-callback-method/109311/1 "2007-07-13T11:25:54Z")

</div>

Hi!

I am trying to do the following. I can’t get it to work, don’t know if  
it even is possible but it would be nice. If it is not possible to do it  
the way I try here is there any other good approach?

My reason to use a callback is to keep the code size down and avoid  
duplicate code. in one case I would use create\_xml\_str and in the other  
case create\_h\_str

I have cut out a lot of code to keep the size down, tell me if you need  
to see more.

###--------------------------------------------------------------------

### header\_data.rb

###--------------------------------------------------------------------  
class Header\_Data  
def create\_xml\_str

# returns a xml-formated string

end

def create\_h\_str

# returns a h-formated string

end

end

###--------------------------------------------------------------------

### header\_data\_array.rb

###--------------------------------------------------------------------  
/…/  
class Header\_Data\_Array

def interpret\_layout(t, callback)  
result = String.new  
case  
when (t.match(/empty/))  
result = “\n\n”

```
when (t.match(/^\d{1,4}/))
  a = @data_array[t.to_i]
  # here a tries to call the callback (crash...)
  a.callback.call()

when (t.match(/[A-Z]*/))
  result = create_subtitle_str(t)

end
return result

```

end

def create\_file(file\_name, layout)  
# get the callback and pass it in the method call  
function = Header\_Data.new.method(:create\_xml\_string)  
layout = layout.map{|l| interpret\_layout(l, function)}

end  
/…/

---

<div class="post-metadata">

**Author:** ![micke](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ecae2f/32.png) [@micke](https://www.ruby-forum.com/u/micke)\
**Post date:** [July 13, 2007, 11:56am UTC](https://www.ruby-forum.com/t/help-with-passing-a-callback-method/109311/2 "2007-07-13T11:56:00Z")

</div>

2007/7/13, Micke L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> I am trying to do the following. I can’t get it to work, don’t know if  
> it even is possible but it would be nice. If it is not possible to do it  
> the way I try here is there any other good approach?
> 
> My reason to use a callback is to keep the code size down and avoid  
> duplicate code. in one case I would use create\_xml\_str and in the other  
> case create\_h\_str
> 
> I have cut out a lot of code to keep the size down, tell me if you need  
> to see more.

I’d rather here where you want to put the callback and what it is  
supposed to do.

The generic answer would be: use a block as callback. You can even  
store it somewhere or pass it on:

def foo(&b)  
puts “calling”  
b.call  
end

def bar(&x)  
puts “delegating”  
foo(&x)  
end

bar do  
puts “block”  
end

> end  
> def interpret\_layout(t, callback)  
> when (t.match(/[A-Z]\*/))  
> function = Header\_Data.new.method(:create\_xml\_string)  
> layout = layout.map{|l| interpret\_layout(l, function)}
> 
> end  
> /…/

Kind regards

robert

---

<div class="post-metadata">

**Author:** ![micke](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ecae2f/32.png) [@micke](https://www.ruby-forum.com/u/micke)\
**Post date:** [July 13, 2007, 12:00pm UTC](https://www.ruby-forum.com/t/help-with-passing-a-callback-method/109311/3 "2007-07-13T12:00:01Z")

</div>

On 7/13/07, Micke L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I have cut out a lot of code to keep the size down, tell me if you need
> 
> /…/  
> # here a tries to call the callback (crash…)
> 
> def create\_file(file\_name, layout)  
> # get the callback and pass it in the method call  
> function = Header\_Data.new.method(:create\_xml\_string)  
> layout = layout.map{|l| interpret\_layout(l, function)}
> 
> end  
> /…/

Hey Mike,

I think what you are trying to do is quite possible, I often use a  
callback class implementation like this:

class Callback  
def initialize &block  
return unless block  
@callback ||= []  
@callback \<\< block  
end

def callback &block  
@callback ||= []  
@callback \<\< block  
end

def trigger \*args  
while cb = @callback.shift  
cb.call(\*args)  
end  
end  
end

now from wherever you are calling method interpret\_layout, before  
calling interpret\_layout you can create an instance of Callback class  
and pass it to method interpret\_layout.

Something like this:

callback = Callback.new { #soemthing that you need to do }  
interpret\_layout(t,callback)

now in method interpret\_layout you can do this:

callback.trigger some\_arg

and the block that you attached while creating the callback would be  
triggered.

---

<div class="post-metadata">

**Author:** ![micke](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ecae2f/32.png) [@micke](https://www.ruby-forum.com/u/micke)\
**Post date:** [July 13, 2007, 12:59pm UTC](https://www.ruby-forum.com/t/help-with-passing-a-callback-method/109311/4 "2007-07-13T12:59:23Z")

</div>

Thanks for the quick replies guys!

I’ll try it out now and let you know how it went

– Micke

---

<div class="post-metadata">

**Author:** ![micke](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/ecae2f/32.png) [@micke](https://www.ruby-forum.com/u/micke)\
**Post date:** [July 13, 2007, 4:38pm UTC](https://www.ruby-forum.com/t/help-with-passing-a-callback-method/109311/5 "2007-07-13T16:38:46Z")

</div>

On 7/13/07, Robert K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > to see more.  
> > end
> 
> def bar(&x)  
> puts “delegating”  
> foo(&x)  
> end
> 
> bar do  
> puts “block”  
> end

Damn you Robert. 🙂
