# Adding a =~ method to the Method class

**URL:** <https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380>\
**Category:** Ruby\
**Created:** [May 7, 2009, 9:02am UTC](https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380 "2009-05-07T09:02:02Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![solidgumby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@solidgumby](https://www.ruby-forum.com/u/solidgumby)\
**Post date:** [May 7, 2009, 9:02am UTC](https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380/1 "2009-05-07T09:02:02Z")

</div>

The Ruby API specifies that objects of the Method class have an instance  
method “==”: “Two method objects are equal if that are bound to the  
same object and contain the same body.”

At this moment, I would very much like it if it also had a “=~” method:  
“two method objects are similar if they contain the same body but are  
NOT necessarily bound to the same object”

unfortunately I’m not currently skilled enough to really understand the  
C code in which the “==” method for the Method class is written. could  
someone help me out here? Below I’ve replicated the C code for the “==”  
method with some changes to reflect what the =~ method would look like:

static VALUE  
method\_similar(method, other)  
VALUE method, other;  
{  
struct METHOD \*m1, \*m2;

```
if (TYPE(other) != T_DATA || RDATA(other)->dmark !=

```

(RUBY\_DATA\_FUNC)bm\_mark)  
return Qfalse; //I Do Not understand what this if statement does  
if (CLASS\_OF(method) != CLASS\_OF(other))  
return Qfalse; //I assume this makes sure that the classes of  
both methods is Method?

```
Data_Get_Struct(method, struct METHOD, m1);//No clue but looks

```

harmless enough  
Data\_Get\_Struct(other, struct METHOD, m2); //No clue but looks  
harmless enough

```
if (m1->klass != m2->klass ||
    m1->rklass != m2->rklass || //this condition looks like it ALSO

```

checks that the classes of both methods is Method, so I must be missing  
something somewhere…  
m1-\>recv != m2-\>recv || // \<-!! Would all that need to happen is  
this line be eliminated??  
m1-\>body != m2-\>body)  
return Qfalse;

```
return Qtrue;

```

}

Also, how can you modify Ruby to include this function, so i can use it  
in my Rails tests?

-Gabe

---

<div class="post-metadata">

**Author:** ![solidgumby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@solidgumby](https://www.ruby-forum.com/u/solidgumby)\
**Post date:** [May 7, 2009, 9:16am UTC](https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380/2 "2009-05-07T09:16:47Z")

</div>

_ruby-1.8.7-p160_  
add to _eval.c,_ after line _9323_:

static VALUE  
method\_similar(method, other)  
VALUE method, other;  
{  
struct METHOD \*m1, \*m2;

```
if (TYPE(other) != T_DATA || RDATA(other)->dmark !=

```

(RUBY\_DATA\_FUNC)bm\_mark)  
return Qfalse;  
if (CLASS\_OF(method) != CLASS\_OF(other))  
return Qfalse;

```
Data_Get_Struct(method, struct METHOD, m1);
Data_Get_Struct(other, struct METHOD, m2);

if (m1->klass != m2->klass || m1->rklass != m2->rklass ||m1->body !=

```

m2-\>body)  
return Qfalse;

```
return Qtrue;

```

}

add to _eval.c_ affter line _10046_:

rb\_define\_method(rb\_cMethod, “=~”, method\_similar, 1);

---

<div class="post-metadata">

**Author:** ![solidgumby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@solidgumby](https://www.ruby-forum.com/u/solidgumby)\
**Post date:** [May 7, 2009, 9:44am UTC](https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380/3 "2009-05-07T09:44:55Z")

</div>

Hi,

In message “Re: Adding a =~ method to the Method class”  
on Thu, 7 May 2009 16:02:09 +0900, Gabriel S.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) writes:

|At this moment, I would very much like it if it also had a “=~” method:  
|“two method objects are similar if they contain the same body but are  
|NOT necessarily bound to the same object”

I am not sure how do you use this similarity check? Example?

```
          matz.

```

---

<div class="post-metadata">

**Author:** ![solidgumby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@solidgumby](https://www.ruby-forum.com/u/solidgumby)\
**Post date:** [May 7, 2009, 10:01am UTC](https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380/4 "2009-05-07T10:01:55Z")

</div>

On Thu, May 7, 2009 at 9:02 AM, Gabriel S. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> 

What about

class UnboundMethod  
def similar? other  
case other  
when self.class  
self == other  
when BoundMethod  
self == other.unbind  
else  
false

# or if you prefer

```
     raise WhateverSeemsFit, "blah"
  end

```

end  
end

class BoundMethod  
def similar? other  
case other  
when self.class  
unbind == other.unbind  
etc.etc.

Cheers  
Robert

–  
Si tu veux construire un bateau …  
Ne rassemble pas des hommes pour aller chercher du bois, préparer des  
outils, répartir les tâches, alléger le travail… mais enseigne aux  
gens la nostalgie de l’infini de la mer.

If you want to build a ship, don’t herd people together to collect  
wood and don’t assign them tasks and work, but rather teach them to  
long for the endless immensity of the sea.

---

<div class="post-metadata">

**Author:** ![solidgumby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@solidgumby](https://www.ruby-forum.com/u/solidgumby)\
**Post date:** [May 7, 2009, 11:11am UTC](https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380/5 "2009-05-07T11:11:30Z")

</div>

Thank you for the quick response!

To answer the other post about an example, The particular use I have for  
it was that I had an abstract class deriving from ActiveRecord. It made  
sense to override many of ActiveRecord’s class methods: The  
AbstractClass methods are passed some params in addition to those  
standard to the ActiveRecord method, which it then uses those params to  
delegate onto the correct concrete sub class, to which it passes the  
standard ActiveRecord params. However, in the subclasses of this  
abstract class, I re-instate the ActiveRecord class methods.

So, in order to test that I had actually reinstated the ActiveRecord  
methods, I needed to assert that my concrete sub class was using the  
ActiveRecord method and not the abstract one.

so…

!(MyAbstractClass.method(:find) == ActiveRecord::Base.method(:find))

but,

MyConcreteSubclass.method(:find) =~ ActiveRecord::Base.method(:find)

incidentally, since posting I attempted to go to bed, but couldn’t, kept  
on thinking about the problem, when I remembered vaguely about unbound  
methods and came up with this purely ruby method solution:

def test\_class\_methods\_similar(klass1, klass2, method\_name\_symbol)  
unbound\_method1 = klass1.method(method\_name\_symbol).unbind  
unbound\_method2 = klass2.method(method\_name\_symbol).unbind  
unbound\_method1 == unbound\_method2  
end

The importance of the test truly came out when it helped me catch a bug

- I had overwritten many methods, and had accidentally overwritten  
destroy with destroy\_all.

however, I like the posted solutions better for readability and the fact  
that it can be called directly from a class.

and, did that post really come from matz? I ask because seeing as how  
I’m fairly new, (to Ruby, to Rails, etc.) and this is my first post ever  
to the Ruby forum, I’m feeling a slight sense of awe. just want to say,  
Ruby is a beautiful language. It has made me love programming after  
many of my college courses had pretty much destroyed any such thought.

I must ask, any chance Method.=~ could make it into the Ruby codebase?  
I figure it must have a lot more uses whenever a solution involves  
overriding/passing around methods between classes, including most any  
use of alias\_method?

-Gabe

KDr2 wrote:

> _ruby-1.8.7-p160_  
> add to _eval.c,_ after line _9323_:
> 
> static VALUE  
> method\_similar(method, other)  
> VALUE method, other;  
> {  
> struct METHOD \*m1, \*m2;
> 
> ```
> if (TYPE(other) != T_DATA || RDATA(other)->dmark !=
> 
> ```
> 
> (RUBY\_DATA\_FUNC)bm\_mark)  
> return Qfalse;  
> if (CLASS\_OF(method) != CLASS\_OF(other))  
> return Qfalse;
> 
> ```
> Data_Get_Struct(method, struct METHOD, m1);
> Data_Get_Struct(other, struct METHOD, m2);
> 
> if (m1->klass != m2->klass || m1->rklass != m2->rklass ||m1->body !=
> 
> ```
> 
> m2-\>body)  
> return Qfalse;
> 
> ```
> return Qtrue;
> 
> ```
> 
> }
> 
> add to _eval.c_ affter line _10046_:
> 
> rb\_define\_method(rb\_cMethod, “=~”, method\_similar, 1);

---

<div class="post-metadata">

**Author:** ![solidgumby](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/4da419/32.png) [@solidgumby](https://www.ruby-forum.com/u/solidgumby)\
**Post date:** [May 7, 2009, 11:22am UTC](https://www.ruby-forum.com/t/adding-a-method-to-the-method-class/167380/6 "2009-05-07T11:22:08Z")

</div>

Robert D. wrote:

> 

and thanks for this too, now I can add it without having to write C and  
recompile!

> Cheers  
> Robert

Cheers indeed!  
-Gabe
