# Method\_missing to define\_method

**URL:** <https://rubytalk.org/t/method-missing-to-define-method/29702>\
**Category:** ruby-talk\
**Created:** [7 August 2006 03:07 UTC](https://rubytalk.org/t/method-missing-to-define-method/29702 "2006-08-07T03:07:37Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Matt\_Todd](https://avatars.discourse-cdn.com/v4/letter/m/ed8c4c/32.png) [@Matt\_Todd](https://rubytalk.org/u/Matt_Todd)\
**Post date:** [7 August 2006 03:07 UTC](https://rubytalk.org/t/method-missing-to-define-method/29702/1 "2006-08-07T03:07:37Z")

</div>

Given the circumstance that you don't want to explicitly predefine  
your methods for properties, etc, but that you're certain your  
parameters won't somehow change to affect your design, would it be  
beneficial to have method\_missing define the method so that  
method\_missing doesn't have to be called in case the property special  
method is called again?

For instance...

class Person  
&nbsp;&nbsp;@attributes = {}  
&nbsp;&nbsp;def initialize attributes  
&nbsp;&nbsp;&nbsp;&nbsp;@attributes.merge! attributes  
&nbsp;&nbsp;end  
&nbsp;&nbsp;def method\_missing name  
&nbsp;&nbsp;&nbsp;&nbsp;if @attributes.has\_key? name  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class\_eval do  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(name) do |name|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@attributes[name]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# other magic  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
end

So, if I do...

p = Person.new { :name =\> "Papa", :age =\> 66, :phone =\> "404-932-3955" }

the first time I ask for...

p.age

the method :age is created. And the next time I call it, then it just  
executes the method I juist created.

So, the point in all of this (and in not using attribute accessors and  
the like) is to find out if it makes sense to dynamically define  
methods for accessing it on use, as opposed to by default? Is there a  
real benefit? Would it just make more sense to keep using  
method\_missing ?

And, consider that this example is very simple, but what if there are  
more advanced methods having to be created for attributes or  
what-have-you (such as Person#find\_by\_foo\_and\_bar)?

Just trying to see what the community believes to be a better  
practice! (Despite the recent argument against best practices.)

M.T.

---

<div class="post-metadata">

**Author:** ![Erik\_Veenstra1](https://avatars.discourse-cdn.com/v4/letter/e/f04885/32.png) [@Erik\_Veenstra1](https://rubytalk.org/u/Erik_Veenstra1)\
**Post date:** [7 August 2006 09:38 UTC](https://rubytalk.org/t/method-missing-to-define-method/29702/2 "2006-08-07T09:38:25Z")

</div>

> class Person  
> &nbsp;&nbsp;&nbsp;@attributes = {}

This is not going to work... Well, it is going to work, but it  
doesn't do what you expected (I suppose)... You're referring to  
the instance variable of the class, which isn't the same has  
the instance variable of an instance of the class.

> &nbsp;&nbsp;&nbsp;def initialize attributes  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@attributes.merge! attributes  
> &nbsp;&nbsp;&nbsp;end

Because of the previous error, you're calling merge! of nil...  
Why not "@attributes = attributes", as usual? You usually  
initialize an object only once, anyway.

> &nbsp;&nbsp;&nbsp;def method\_missing name  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if @attributes.has\_key? name  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class\_eval do

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object#.class\_eval ???

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(name) do |name|

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(name) do

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@attributes[name]  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.send(name)

> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# other magic  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end  
> end
> 
> And, consider that this example is very simple,

... but it doesn't work... ;]

gegroet,  
Erik V. - [http://www.erikveen.dds.nl/](http://www.erikveen.dds.nl/)

---

<div class="post-metadata">

**Author:** ![A\_S\_Bradbury](https://avatars.discourse-cdn.com/v4/letter/a/df705f/32.png) [@A\_S\_Bradbury](https://rubytalk.org/u/A_S_Bradbury)\
**Post date:** [8 August 2006 11:54 UTC](https://rubytalk.org/t/method-missing-to-define-method/29702/3 "2006-08-08T11:54:34Z")

</div>

Have you seen OpenStruct in the standard library?

require 'ostruct'  
p = OpenStruct.new({ :name =\> "Papa", :age =\> 66, :phone =\> "404-932-3955" })

You can add new fields after object creation, p.occupation="Doctor".

I'm also curious as to whether there's any advantage to defining methods (as  
OpenStruct does) vs just looking up hash keys in method\_missing.

Alex

> **···**
>
> On Monday 07 August 2006 04:07, Matt Todd wrote:
> 
> > Given the circumstance that you don't want to explicitly predefine  
> > your methods for properties, etc, but that you're certain your  
> > parameters won't somehow change to affect your design, would it be  
> > beneficial to have method\_missing define the method so that  
> > method\_missing doesn't have to be called in case the property special  
> > method is called again?
> > 
> > For instance...
> > 
> > class Person  
> > &nbsp;&nbsp;@attributes = {}  
> > &nbsp;&nbsp;def initialize attributes  
> > &nbsp;&nbsp;&nbsp;&nbsp;@attributes.merge! attributes  
> > &nbsp;&nbsp;end  
> > &nbsp;&nbsp;def method\_missing name  
> > &nbsp;&nbsp;&nbsp;&nbsp;if @attributes.has\_key? name  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class\_eval do  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;define\_method(name) do |name|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@attributes[name]  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;else  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# other magic  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;end  
> > end
> > 
> > So, if I do...
> > 
> > p = Person.new { :name =\> "Papa", :age =\> 66, :phone =\> "404-932-3955" }
> > 
> > the first time I ask for...
> > 
> > p.age
> > 
> > the method :age is created. And the next time I call it, then it just  
> > executes the method I juist created.

---

<div class="post-metadata">

**Author:** ![Dr\_Nic](https://avatars.discourse-cdn.com/v4/letter/d/bc8723/32.png) [@Dr\_Nic](https://rubytalk.org/u/Dr_Nic)\
**Post date:** [8 August 2006 12:39 UTC](https://rubytalk.org/t/method-missing-to-define-method/29702/4 "2006-08-08T12:39:20Z")

</div>

Matt Todd wrote:

> Given the circumstance that you don't want to explicitly predefine  
> your methods for properties, etc, but that you're certain your  
> parameters won't somehow change to affect your design, would it be  
> beneficial to have method\_missing define the method so that  
> method\_missing doesn't have to be called in case the property special  
> method is called again?

Have a look in the ActiveRecord gem - it does a similar thing.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Matt\_Todd](https://avatars.discourse-cdn.com/v4/letter/m/ed8c4c/32.png) [@Matt\_Todd](https://rubytalk.org/u/Matt_Todd)\
**Post date:** [8 August 2006 13:12 UTC](https://rubytalk.org/t/method-missing-to-define-method/29702/5 "2006-08-08T13:12:11Z")

</div>

OK: hopefully they chose the better performer of the two!

I'll definitely check out the OpenStruct. I think I definitely missed  
out on the struct goodness when I learned C++ those few years ago. I  
see Mauricio using it a good bit in his code, so it's been tickling my  
curiosity for some time.

Thanks for the comments.

M.T.
