# Method\_missing question

**URL:** <https://rubytalk.org/t/method-missing-question/33759>\
**Category:** ruby-talk\
**Created:** [15 December 2006 09:01 UTC](https://rubytalk.org/t/method-missing-question/33759 "2006-12-15T09:01:18Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Peter\_Szinek3](https://avatars.discourse-cdn.com/v4/letter/p/ea5d25/32.png) [@Peter\_Szinek3](https://rubytalk.org/u/Peter_Szinek3)\
**Post date:** [15 December 2006 09:01 UTC](https://rubytalk.org/t/method-missing-question/33759/1 "2006-12-15T09:01:18Z")

</div>

Hello,

I am using method\_missing to build a structure (similar to a tree) like  
this:

P.book do  
&nbsp;&nbsp;P.title  
&nbsp;&nbsp;P.price  
end

class P  
&nbsp;&nbsp;def self.method\_missing(method\_name, \*args, &block)  
&nbsp;&nbsp;&nbsp;&nbsp;#add a node with name 'method\_name.to\_s' to the tree etc.  
&nbsp;&nbsp;end  
end

Now, the problem is I would like to write the above example like this:

book do  
&nbsp;&nbsp;title  
&nbsp;&nbsp;price  
end

i.e. without the Ps.  
P's sole purpose is to define method\_missing - I did not want to  
override Object.method\_missing since I would like to release this code  
to the wild and I think it could collide with my potential future user's  
Object.method\_missing.

I have then experimented with modules (mimicking namespace  
functionality) but that still did not provide the possibility to omit  
the class name. I would need something equivalent to include - you can  
omit the module name if you include the module - but with classes.

I have no idea if this is possible in Ruby, but is there something like  
run this code in a different context or something?

TIA,  
Peter

> **···**
>
> \_\_  
> [http://www.rubyrailways.com](http://www.rubyrailways.com)

---

<div class="post-metadata">

**Author:** ![Michael\_Fellinger1](https://avatars.discourse-cdn.com/v4/letter/m/e47774/32.png) [@Michael\_Fellinger1](https://rubytalk.org/u/Michael_Fellinger1)\
**Post date:** [15 December 2006 09:14 UTC](https://rubytalk.org/t/method-missing-question/33759/2 "2006-12-15T09:14:33Z")

</div>

> Hello,
> 
> I am using method\_missing to build a structure (similar to a tree) like  
> this:
> 
> P.book do  
> &nbsp;&nbsp;P.title  
> &nbsp;&nbsp;P.price  
> end
> 
> class P  
> &nbsp;&nbsp;def self.method\_missing(method\_name, \*args, &block)  
> &nbsp;&nbsp;&nbsp;&nbsp;#add a node with name 'method\_name.to\_s' to the tree etc.  
> &nbsp;&nbsp;end  
> end
> 
> Now, the problem is I would like to write the above example like this:
> 
> book do  
> &nbsp;&nbsp;title  
> &nbsp;&nbsp;price  
> end
> 
> i.e. without the Ps.  
> P's sole purpose is to define method\_missing - I did not want to  
> override Object.method\_missing since I would like to release this code  
> to the wild and I think it could collide with my potential future user's  
> Object.method\_missing.
> 
> I have then experimented with modules (mimicking namespace  
> functionality) but that still did not provide the possibility to omit  
> the class name. I would need something equivalent to include - you can  
> omit the module name if you include the module - but with classes.
> 
> I have no idea if this is possible in Ruby, but is there something like  
> run this code in a different context or something?

actually, there is - it is called script and you can find it described here:  
[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/100429](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/100429)

> **···**
>
> On 12/15/06, Peter Szinek \<peter@rubyrailways.com\> wrote:
> 
> > TIA,  
> > Peter
> > 
> > \_\_  
> > [http://www.rubyrailways.com](http://www.rubyrailways.com)

---

<div class="post-metadata">

**Author:** ![George3](https://avatars.discourse-cdn.com/v4/letter/g/51bf81/32.png) [@George3](https://rubytalk.org/u/George3)\
**Post date:** [16 December 2006 02:18 UTC](https://rubytalk.org/t/method-missing-question/33759/3 "2006-12-16T02:18:11Z")

</div>

Hi Peter,

This sort of thing probably already exists somewhere, but I don't know  
what it's called. (The 'script' that Michael mentioned looks like  
something else to me... ?)

So anyway, here's a starting point. The trick is to use instance\_eval  
to change the value of 'self' within the block.

class Node  
&nbsp;&nbsp;# Rename all existing methods to start with '\_\_', so they're not  
&nbsp;&nbsp;# likely to collide with your attribute names. We'll leave some  
&nbsp;&nbsp;# methods alone, since they're necessary for some basic operations.  
&nbsp;&nbsp;methods = (instance\_methods + private\_instance\_methods)  
&nbsp;&nbsp;methods = methods - %w'\_\_send\_\_ \_\_id\_\_ initialize inspect'  
&nbsp;&nbsp;methods.each{|m| alias\_method("\_\_#{m}", m); undef\_method(m)}

&nbsp;&nbsp;def method\_missing(\*args, &block)  
&nbsp;&nbsp;&nbsp;&nbsp;key, val = \*args  
&nbsp;&nbsp;&nbsp;&nbsp;if block  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args.length == 1 or  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ArgumentError, "value and block given"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node = Node.new  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_instance\_variable\_set("@#{key}", node)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node.\_\_instance\_eval(&block)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return node  
&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;args.length \<= 2 or  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise ArgumentError, "too many arguments"  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if args.length \> 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_instance\_variable\_set("@#{key}", val)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return \_\_instance\_variable\_get("@#{key}")  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
end

### Usage

node = Node.new  
node.root do  
&nbsp;&nbsp;a 1  
&nbsp;&nbsp;b 2  
&nbsp;&nbsp;c do  
&nbsp;&nbsp;&nbsp;&nbsp;d 3  
&nbsp;&nbsp;&nbsp;&nbsp;e 4  
&nbsp;&nbsp;end  
end  
p node.root.c.d #=\> 3  
p node.root.c #=\> #\<Node:0xb7dd55c4 @d=3, @e=4\>  
p node #=\> #\<Node:0xb7ddb8ac @root=#\<Node:...\>\>

> **···**
>
> On 12/15/06, Peter Szinek \<peter@rubyrailways.com\> wrote:
> 
> > Now, the problem is I would like to write the above example like this:
> > 
> > book do  
> > &nbsp;&nbsp;title  
> > &nbsp;&nbsp;price  
> > end
> > 
> > i.e. without the Ps.  
> > P's sole purpose is to define method\_missing - I did not want to  
> > override Object.method\_missing since I would like to release this code  
> > to the wild and I think it could collide with my potential future user's  
> > Object.method\_missing.
> > 
> > I have then experimented with modules (mimicking namespace  
> > functionality) but that still did not provide the possibility to omit  
> > the class name. I would need something equivalent to include - you can  
> > omit the module name if you include the module - but with classes.
> > 
> > I have no idea if this is possible in Ruby, but is there something like  
> > run this code in a different context or something?

---

<div class="post-metadata">

**Author:** ![Joel\_VanderWerf1](https://avatars.discourse-cdn.com/v4/letter/j/94ad74/32.png) [@Joel\_VanderWerf1](https://rubytalk.org/u/Joel_VanderWerf1)\
**Post date:** [16 December 2006 22:13 UTC](https://rubytalk.org/t/method-missing-question/33759/4 "2006-12-16T22:13:47Z")

</div>

George Ogata wrote:

> > Now, the problem is I would like to write the above example like this:
> > 
> > book do  
> > &nbsp;&nbsp;title  
> > &nbsp;&nbsp;price  
> > end

...

> This sort of thing probably already exists somewhere, but I don't know  
> what it's called. (The 'script' that Michael mentioned looks like  
> something else to me... ?)

Yes, "script" is something else. It's for loading an external "script" inside of a module, to confine it to a namespace. It's like "load(..., true)", but you can access the anonymous module.

It has nothing to do with defining a special syntax like the OP wanted.

> **···**
>
> > On 12/15/06, Peter Szinek \<peter@rubyrailways.com\> wrote:
> 
> --  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

---

<div class="post-metadata">

**Author:** ![JM1](https://avatars.discourse-cdn.com/v4/letter/j/db5fbb/32.png) [@JM1](https://rubytalk.org/u/JM1)\
**Post date:** [17 December 2006 07:35 UTC](https://rubytalk.org/t/method-missing-question/33759/5 "2006-12-17T07:35:59Z")

</div>

> So anyway, here's a starting point. The trick is to use instance\_eval  
> to change the value of 'self' within the block.

More straightforward to grab the block, make it a method of the current  
object, then call that method?

require 'pp'

class ReadableThing  
&nbsp;&nbsp;def book &block  
&nbsp;&nbsp;&nbsp;&nbsp;ugly\_call\_to\_get\_the\_eigenclass = class \<\< self; self; end  
&nbsp;&nbsp;&nbsp;&nbsp;ugly\_call\_to\_get\_the\_eigenclass.send :define\_method, :\_\_\_secret\_method,  
block  
&nbsp;&nbsp;&nbsp;&nbsp;send :\_\_\_secret\_method  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def title  
&nbsp;&nbsp;&nbsp;&nbsp;pp 'a title'  
&nbsp;&nbsp;end  
end

r = ReadableThing.new

r.book do  
&nbsp;&nbsp;puts "self is: #{self.inspect}\n"  
&nbsp;&nbsp;title  
end

C:\rx\rv\bin\>ruby r.rb  
self is: #\<ReadableThing:0x28e40fc\>  
"a title"

It does leave a reference to the block lying around - you'd probably want to  
clean that up for production code.

-- James Moore
