Adding a =~ method to the Method class

Discussion in 'Ruby' started by Gabriel Saravia, May 7, 2009.

  1. 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
    --
    Posted via http://www.ruby-forum.com/.
     
    Gabriel Saravia, May 7, 2009
    #1
    1. Advertising

  2. Gabriel Saravia

    KDr2 Guest

    [Note: parts of this message were removed to make it a legal post.]

    *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);

    On Thu, May 7, 2009 at 3:02 PM, Gabriel Saravia <>wrote:

    > CLASS_OF(method)





    --
    Best Regards,
    -- KDr2, at x-macro.com.
     
    KDr2, May 7, 2009
    #2
    1. Advertising

  3. Gabriel Saravia

    Robert Dober Guest

    On Thu, May 7, 2009 at 9:02 AM, Gabriel Saravia <> wr=
    ote:
    >

    What about

    class UnboundMethod
    def similar? other
    case other
    when self.class
    self =3D=3D other
    when BoundMethod
    self =3D=3D 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 =3D=3D other.unbind
    etc.etc.

    Cheers
    Robert



    --=20
    Si tu veux construire un bateau ...
    Ne rassemble pas des hommes pour aller chercher du bois, pr=E9parer des
    outils, r=E9partir les t=E2ches, all=E9ger le travail=85 mais enseigne aux
    gens la nostalgie de l=92infini de la mer.

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

    --
    Antoine de Saint-Exup=E9ry
     
    Robert Dober, May 7, 2009
    #3
  4. 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);


    --
    Posted via http://www.ruby-forum.com/.
     
    Gabriel Saravia, May 7, 2009
    #4
  5. Robert Dober wrote:
    >


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

    > Cheers
    > Robert


    Cheers indeed!
    -Gabe
    --
    Posted via http://www.ruby-forum.com/.
     
    Gabriel Saravia, May 7, 2009
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. E11
    Replies:
    1
    Views:
    4,789
    Thomas Weidenfeller
    Oct 12, 2005
  2. Pawel_Iks
    Replies:
    3
    Views:
    536
    terminator
    Jul 31, 2007
  3. Replies:
    3
    Views:
    932
    Roedy Green
    Jan 28, 2008
  4. marekw2143
    Replies:
    3
    Views:
    1,366
    marekw2143
    Jul 25, 2009
  5. Raj Singh
    Replies:
    2
    Views:
    200
    Rick DeNatale
    May 29, 2008
Loading...

Share This Page