John Merlino
2011-May-17 01:20 UTC
how instance_eval on Object class creating class methods and not instance methods?
Hey all, I am a little confused about a tutorial I read. Here''s an example below taken from the tutorial: Object.instance_eval do def has_attribute( *attrs ) attrs.each do | attr | self.class_eval %Q{ def #{attr}=(val) instance_variable_set("@#{attr}", val) end def #{attr} instance_variable_get("@#{attr}") end } end end end class A has_attribute :my_attribute, :another_attribute end a = A.new puts a.methods - Object.methods # => ["my_attribute", my_attribute=", "another_attribute", "another_attribute="] a.my_attribute = 1 a.my_attribute # => 1 a.another_attribute = "A String" a.another_attribute # => "A String" THe guy says: "The first instance_eval is used to add class method has_attribute into Object so that we can call it in all the inherited class." I''m a little thrown off by this statement. First, Object itself is an instance of class Class. Someone here even said before "Object is an instance of Class". So "class Object end "implies that Object is an instance of class, equivalent to: Object = Class.new. Hence, we can invoke instance_eval on Object, since Object is an instance. What confuses me here is has_attribute appears to be an instance method (e.g. def a end) not class method (e.g. def self.a end). So why does guy say we add class method has_attribute? In fact, the difference between Object class and Class class is that when you add methods to class Class, those methods become available to any class that is created as well (since all classes created using class construct inherit from Class) and you can use those methods within any class. However, that''s not what we do above. We extend Object above. When you instantiate a class, you inherently create an object instance, so that object instance should have available the methods defined in Object. So then how can we access that method within a class, such as that being done in class A above? Thanks for response -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Frederick Cheung
2011-May-17 06:57 UTC
Re: how instance_eval on Object class creating class methods and not instance methods?
On 17 May 2011, at 02:20, John Merlino <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> THe guy says: > "The first instance_eval is used to add class method has_attribute into > Object so that we can call it in all the inherited class." > > I''m a little thrown off by this statement. First, Object itself is an > instance of class Class. Someone here even said before "Object is an > instance of Class". So "class Object end "implies that Object is an > instance of class, equivalent to: Object = Class.new. Hence, we can > invoke instance_eval on Object, since Object is an instance. What > confuses me here is has_attribute appears to be an instance method (e.g. > def a end) not class method (e.g. def self.a end). So why does guy say > we add class method has_attribute? >Well a class method called has_attribute has been added. I think this is just awkward phrasing - instance_eval is indeed invoked on Object. As to why that results in a class method, that''s sort of what instance_eval does - there are lots of articles on instance_eval and class_eval etc. that go into the details Fred.> In fact, the difference between Object class and Class class is that > when you add methods to class Class, those methods become available to > any class that is created as well (since all classes created using class > construct inherit from Class) and you can use those methods within any > class. However, that''s not what we do above. We extend Object above. > When you instantiate a class, you inherently create an object instance, > so that object instance should have available the methods defined in > Object. So then how can we access that method within a class, such as > that being done in class A above? > > Thanks for response > > -- > Posted via http://www.ruby-forum.com/. > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Max Schubert
2011-May-17 08:58 UTC
Re: how instance_eval on Object class creating class methods and not instance methods?
I think you are just confused by the overloaded use of the words objct and class as opposed to the ruby classes named Object and Class. This diagram / project might help clarify http://objectgraph.rubyforge.org/dotOG.html From http://objectgraph.rubyforge.org/ Max On 5/16/11, John Merlino <lists-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Hey all, > > I am a little confused about a tutorial I read. Here''s an example below > taken from the tutorial: > > Object.instance_eval do > def has_attribute( *attrs ) > attrs.each do | attr | > self.class_eval %Q{ > def #{attr}=(val) > instance_variable_set("@#{attr}", val) > end > > def #{attr} > instance_variable_get("@#{attr}") > end > } > end > end > end > > class A > has_attribute :my_attribute, :another_attribute > end > > a = A.new > > puts a.methods - Object.methods > # => ["my_attribute", my_attribute=", "another_attribute", > "another_attribute="] > > a.my_attribute = 1 > a.my_attribute > # => 1 > > a.another_attribute = "A String" > a.another_attribute > # => "A String" > > THe guy says: > "The first instance_eval is used to add class method has_attribute into > Object so that we can call it in all the inherited class." > > I''m a little thrown off by this statement. First, Object itself is an > instance of class Class. Someone here even said before "Object is an > instance of Class". So "class Object end "implies that Object is an > instance of class, equivalent to: Object = Class.new. Hence, we can > invoke instance_eval on Object, since Object is an instance. What > confuses me here is has_attribute appears to be an instance method (e.g. > def a end) not class method (e.g. def self.a end). So why does guy say > we add class method has_attribute? > > In fact, the difference between Object class and Class class is that > when you add methods to class Class, those methods become available to > any class that is created as well (since all classes created using class > construct inherit from Class) and you can use those methods within any > class. However, that''s not what we do above. We extend Object above. > When you instantiate a class, you inherently create an object instance, > so that object instance should have available the methods defined in > Object. So then how can we access that method within a class, such as > that being done in class A above? > > Thanks for response > > -- > Posted via http://www.ruby-forum.com/. > > -- > You received this message because you are subscribed to the Google Groups > "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to > rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > For more options, visit this group at > http://groups.google.com/group/rubyonrails-talk?hl=en. > >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
John Merlino
2011-May-17 19:23 UTC
Re: how instance_eval on Object class creating class methods and not instance methods?
Let me see if I fully understand this. This: Object.instance_eval def a puts ''a'' end end is equivalent to this: class Object def self.a puts ''a'' end end Basically, instance_eval invoked on Object creates a new class method for the Object class (or for class Class? and if it is class Class, then why bother invoking instance_eval it on Object?). The reason why I say this is because that method is now available to class Class and all classes created, since they all inherit from class Class when using the class construct. The only logical explanation I can come up for this behavior is that whenever you create a class method, the method is automatically copied to class Class and therefore all classes inherit from it. Correct? If so, then why use instance_eval on Object? Example: ruby-1.8.7-p330 :001 > class Object ruby-1.8.7-p330 :002?> def self.a ruby-1.8.7-p330 :003?> puts ''a'' ruby-1.8.7-p330 :004?> end ruby-1.8.7-p330 :005?> end ruby-1.8.7-p330 :006 > class A ruby-1.8.7-p330 :007?> end ruby-1.8.7-p330 :011 > Object.a a ruby-1.8.7-p330 :008 > A.a a This fails because @a is an instance method that does not have access to class methods, even class methods of Object: ruby-1.8.7-p330 :009 > @a = A.new => #<A:0x1069a3088> ruby-1.8.7-p330 :010 > @a.a NoMethodError: undefined method `a'' for #<A:0x1069a3088> from (irb):10 from :0 ruby-1.8.7-p330 :015 > @a = Object.new => #<Object:0x1064fcf98> ruby-1.8.7-p330 :016 > @a.a Thanks for response -- Posted via http://www.ruby-forum.com/. -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Adam Stegman
2011-May-18 03:20 UTC
Re: Re: how instance_eval on Object class creating class methods and not instance methods?
It''s not defining it on Class, it''s defining it on the Object class. Every class inherits from Object, so every class inherits that class method. If you define it on a different class, it will belong to that class and its descendants:> String.instance_eval do > def test_method > "test" > end > end > > class A; end > class B < String; end > > A.test_method #=> NoMethodError > B.test_method #=> "test"On May 17, 2011, at 2:23 PM, John Merlino wrote:> Let me see if I fully understand this. > > This: > > Object.instance_eval > def a > puts ''a'' > end > end > > is equivalent to this: > > class Object > def self.a > puts ''a'' > end > end > > Basically, instance_eval invoked on Object creates a new class method > for the Object class (or for class Class? and if it is class Class, then > why bother invoking instance_eval it on Object?). The reason why I say > this is because that method is now available to class Class and all > classes created, since they all inherit from class Class when using the > class construct. The only logical explanation I can come up for this > behavior is that whenever you create a class method, the method is > automatically copied to class Class and therefore all classes inherit > from it. Correct? If so, then why use instance_eval on Object? > > Example: > > ruby-1.8.7-p330 :001 > class Object > ruby-1.8.7-p330 :002?> def self.a > ruby-1.8.7-p330 :003?> puts ''a'' > ruby-1.8.7-p330 :004?> end > ruby-1.8.7-p330 :005?> end > > > ruby-1.8.7-p330 :006 > class A > ruby-1.8.7-p330 :007?> end > > ruby-1.8.7-p330 :011 > Object.a > a > > ruby-1.8.7-p330 :008 > A.a > a > > This fails because @a is an instance method that does not have access to > class methods, even class methods of Object: > ruby-1.8.7-p330 :009 > @a = A.new > => #<A:0x1069a3088> > ruby-1.8.7-p330 :010 > @a.a > NoMethodError: undefined method `a'' for #<A:0x1069a3088> > from (irb):10 > from :0 > > > ruby-1.8.7-p330 :015 > @a = Object.new > => #<Object:0x1064fcf98> > ruby-1.8.7-p330 :016 > @a.a > > Thanks for response > > -- > Posted via http://www.ruby-forum.com/. > > -- > You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. > To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org > For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en. >-- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.