Strange behavior when class_eval'ing a Class object

Just for the sake of learning more about the Ruby object model, I've been doing some experiments, and the following behavior surprised me:

Let's say we have a class Test:

class Test;end

Then, we class_eval Test.class in order to add a method to the Test object:

Test.class.class_eval do
  def foo
    puts 'foo called!'
  end
end

(equivalent to calling Test.class.send(:define_method,:foo) ... )

Then:

irb(main):076:0> Test.foo
=> foo called!

But sending foo to class also works:

irb(main):006:0> Test.class.foo
=> foo called!

I still can't figure out why, though. The Class' singleton_class doesn't contain it (the only possible explanation that came to my mind was that somehow the method was added to the Class' singleton class):

Test.class.singleton_methods
=> [:nesting, :constants]

How does the method lookup work in this case? Why does sending :foo to Test.class also calls the method ? Am I missing something ?

···

----

As a reference, I did the same thing with an instance of Test:

irb(main):001:0> class Test;end
=> nil
irb(main):002:0> _foo = Test.new
=> #<Test:0x007fa2c39e2f38>
irb(main):003:0> _foo.class.class_eval do
irb(main):004:1* def foo
irb(main):005:2> puts 'foo called!'
irb(main):006:2> end
irb(main):007:1> end
=> :foo
irb(main):008:0> _foo.foo
foo called!
=> nil
irb(main):009:0> _foo.class.foo
NoMethodError: undefined method `foo' for Test:Class

This worked the way I expected it to.

Thanks in advance!

--
Marcelo Serpa

Because Test.class == Class and Class.class == Class

It's kind of swirly.

  class A
    def foo()...;end
  end
  B.is_a? A # so B.foo works
  C.is_a? A # so C.foo works

thus:

  class Class
    def foo()...;end
  end
  Test.is_a? Class # Test.foo works
  Class.is_a? Class # Class.foo works

Matthew Kerwin

···

On Jan 29, 2014 2:31 PM, "Marcelo Serpa" <mlists@fullofcaffeine.com> wrote:

Just for the sake of learning more about the Ruby object model, I've
been doing some experiments, and the following behavior surprised me:

Let's say we have a class Test:

class Test;end

Then, we class_eval Test.class in order to add a method to the Test object:

Test.class.class_eval do
  def foo
    puts 'foo called!'
  end
end

(equivalent to calling Test.class.send(:define_method,:foo) ... )

Then:

irb(main):076:0> Test.foo
=> foo called!

But sending foo to class also works:

irb(main):006:0> Test.class.foo
=> foo called!

I still can't figure out why, though. The Class' singleton_class doesn't
contain it (the only possible explanation that came to my mind was that
somehow the method was added to the Class' singleton class):

Test.class.singleton_methods
=> [:nesting, :constants]

How does the method lookup work in this case? Why does sending :foo to
Test.class also calls the method ? Am I missing something ?

----

As a reference, I did the same thing with an instance of Test:

irb(main):001:0> class Test;end
=> nil
irb(main):002:0> _foo = Test.new
=> #<Test:0x007fa2c39e2f38>
irb(main):003:0> _foo.class.class_eval do
irb(main):004:1* def foo
irb(main):005:2> puts 'foo called!'
irb(main):006:2> end
irb(main):007:1> end
=> :foo
irb(main):008:0> _foo.foo
foo called!
=> nil
irb(main):009:0> _foo.class.foo
NoMethodError: undefined method `foo' for Test:Class

This worked the way I expected it to.

Thanks in advance!

--
Marcelo Serpa

Yep! I just figured out that a few minutes before you sent the message! Eureka :slight_smile:

Thank you very much for taking the time to answer.

Cheers,

···

--
Marcelo Serpa
Sent with Sparrow (http://www.sparrowmailapp.com/?sig\)

On Wednesday, January 29, 2014 at 12:45 AM, Matthew Kerwin wrote:

Because Test.class == Class and Class.class == Class
It's kind of swirly.
  class A
    def foo()...;end
  end
  B.is_a? A # so B.foo works
  C.is_a? A # so C.foo works
thus:
  class Class
    def foo()...;end
  end
  Test.is_a? Class # Test.foo works
  Class.is_a? Class # Class.foo works
Matthew Kerwin
On Jan 29, 2014 2:31 PM, "Marcelo Serpa" <mlists@fullofcaffeine.com (mailto:mlists@fullofcaffeine.com)> wrote:
> Just for the sake of learning more about the Ruby object model, I've been doing some experiments, and the following behavior surprised me:
>
> Let's say we have a class Test:
>
> class Test;end
>
> Then, we class_eval Test.class in order to add a method to the Test object:
>
> Test.class.class_eval do
> def foo
> puts 'foo called!'
> end
> end
>
> (equivalent to calling Test.class.send(:define_method,:foo) ... )
>
> Then:
>
> irb(main):076:0> Test.foo
> => foo called!
>
> But sending foo to class also works:
>
> irb(main):006:0> Test.class.foo
> => foo called!
>
>
> I still can't figure out why, though. The Class' singleton_class doesn't contain it (the only possible explanation that came to my mind was that somehow the method was added to the Class' singleton class):
>
> Test.class.singleton_methods
> => [:nesting, :constants]
>
>
> How does the method lookup work in this case? Why does sending :foo to Test.class also calls the method ? Am I missing something ?
>
> ----
>
> As a reference, I did the same thing with an instance of Test:
>
> irb(main):001:0> class Test;end
> => nil
> irb(main):002:0> _foo = Test.new
> => #<Test:0x007fa2c39e2f38>
> irb(main):003:0> _foo.class.class_eval do
> irb(main):004:1* def foo
> irb(main):005:2> puts 'foo called!'
> irb(main):006:2> end
> irb(main):007:1> end
> => :foo
> irb(main):008:0> _foo.foo
> foo called!
> => nil
> irb(main):009:0> _foo.class.foo
> NoMethodError: undefined method `foo' for Test:Class
>
>
> This worked the way I expected it to.
>
> Thanks in advance!
>
> --
> Marcelo Serpa
>