Remove/undef a class method - ruby

You can dynamically define a class method for a class like so:
class Foo
end
bar = %q{def bar() "bar!" end}
Foo.instance_eval(bar)
But how do you do the opposite: remove/undefine a class method? I suspect Module's remove_method and undef_method methods might be able to be used for this purpose, but all of the examples I've seen after Googling for hours have been for removing/undefining instance methods, not class methods. Or perhaps there's a syntax you can pass to instance_eval to do this as well.
Thanks in advance.

class Foo
def self.bar
puts "bar"
end
end
Foo.bar # => bar
class <<Foo
undef_method :bar
end
# or
class Foo
singleton_class.undef_method :bar
end
Foo.bar # => undefined method `bar' for Foo:Class (NoMethodError)
When you define a class method like Foo.bar, Ruby puts it Foo's singleton class. Ruby can't put it in Foo, because then it would be an instance method. Ruby creates Foo's singleton class, sets the superclass of the singleton class to Foo's superclass, and then sets Foo's superclass to the singleton class:
Foo -------------> Foo(singleton class) -------------> Object
super def bar super
There are a few ways to access the singleton class:
class <<Foo,
Foo.singleton_class,
class Foo; class << self which is commonly use to define class methods.
Note that we used undef_method, we could have used remove_method. The former prevents any call to the method, and the latter only removes the current method, having a fallback to the super method if existing. See Module#undef_method for more information.

This also works for me (not sure if there are differences between undef and remove_method):
class Foo
end
Foo.instance_eval do
def color
"green"
end
end
Foo.color # => "green"
Foo.instance_eval { undef :color }
Foo.color # => NoMethodError: undefined method `color' for Foo:Class

You can remove a method in two easy ways. The drastic
Module#undef_method( )
removes all methods, including the inherited ones. The kinder
Module#remove_method( )
removes the method from the receiver, but it
leaves inherited methods alone.
See below 2 simple example -
Example 1 using undef_method
class A
def x
puts "x from A class"
end
end
class B < A
def x
puts "x from B Class"
end
undef_method :x
end
obj = B.new
obj.x
result -
main.rb:15:in
': undefined methodx' for # (NoMethodError)
Example 2 using remove_method
class A
def x
puts "x from A class"
end
end
class B < A
def x
puts "x from B Class"
end
remove_method :x
end
obj = B.new
obj.x
Result -
$ruby main.rb
x from A class

I guess I can't comment on Adrian's answer because I don't have enough cred, but his answer helped me.
What I found: undef seems to completely remove the method from existence, while remove_method removes it from that class, but it will still be defined on superclasses or other modules that have been extened on this class, etc.

If you would like to remove method with name what calculate dinamically, you should use eigenclasses like:
class Foo
def self.bar
puts "bar"
end
end
name_of_method_to_remove = :bar
eigenclass = class << Foo; self; end
eigenclass.class_eval do
remove_method name_of_method_to_remove
end
this way is better than others answers, becouse here i used class_eval with block. As you now block see current namespace, so you could use your variables to remove methods dinamically

Object.send(:remove_const, :Foo)

Related

When to use self for Ruby Class

Can somebody help me distinguish When we create methods inside class << self block and when we define normal methods.
I saw somewhere code like this, but I don't know concisely the use cases of them
class Foo
def initialize
end
def bar
end
class << self
def foobar
end
end
end
The methods defined right inside a class block are instance methods:
class Foo
def bar
end
end
Methods defined within class << self inside a class block are class methods:
class Foo
class << self
def baz
end
end
end
Instance methods become available to any instance of a given class:
foo = Foo.new
foo.bar
Whereas class methods can be called directly on the class:
Foo.baz
Attempting to call instance methods on the class or vice versa results in an error:
Foo.bar #=> NoMethodError: undefined method `bar' for Foo:Class
foo.baz #=> NoMethodError: undefined method `baz' for #<Foo:0x00007ffe20055a20>
Another way to define class methods is by prefixing the method name with self.:
class Foo
def self.baz
end
end
You could also define them outside the class block, although this is rarely seen:
def Foo.baz
end
Or likewise:
class << Foo
def baz
end
end
Note that defining methods this way is not limited to classes. You can add methods to arbitrary objects, e.g.:
o = Object.new
def o.hello
"hello from o"
end
o.hello
#=> "hello from o"
Or via:
class << o
def hello
"hello from o"
end
end
Internally, these methods are added to the object's singleton class. It's a special purpose class to hold methods for just that instance:
o.singleton_class.instance_methods(false)
#=> [:hello]
For the Foo class above:
Foo.instance_methods(false) #=> [:bar]
Foo.singleton_class.instance_methods(false) #=> [:baz]
So technically, a class method is just an instance method defined on the class' singleton class.
You may need to read up on Ruby's instance and class methods.
But personally, I'd do
class Foo
class << self
def foobar
end
end
end
instead of
class Foo
def self.foobar
end
end
whenever I want to add some class level attributes, or make a method private etc as
class Foo
private
def self.foobar
end
end
wouldn't work the same as
class Foo
class << self
private
def foobar
end
end
end

Is it possible to define class methods within `class_eval`?

I know it's possible to define instance methods using class_eval. Is it possible to define class methods within the context of class_eval?
Yes, it is possible:
class Foo
end
Foo.class_eval do
def self.bar
puts "I'm a class method defined using class_eval and self"
end
def baz
puts "I'm an instance method defined using class_eval without self"
end
end
Foo.bar # => "I'm a class method defined using class_eval and self"
foo = Foo.new
foo.baz # => "I'm an instance method defined using class_eval without self"
As far as I can tell, this is because within class_eval, self is the Foo class, and doing def Foo.bar would create a class method.
Foo.class_eval do
...
end
is identical to:
class Foo
...
end
We need Module#class_eval to operate on a variable that holds the name of a class. For example, if:
klass = Foo
you can write:
klass.class_eval do
...
end
whereas the keyword class demands a constant.
Here class_eval does two things:
it changes self to the value of klass (Foo); and then it
"opens" the value of klass (Foo) in the same way the keyword class does.

How do I hide a method from a superclass?

I have a method in a superclass from a third-party gem which I want to hide. I would prefer if it is impossible to call this method at all, so not just override it and leave the body empty.
I believe this may be what you're looking for:
undef_method :foo
This will prevent any calls to the method foo.
In contrast, this will not achieve the same effect:
remove_method :foo
That will remove the method from the child, but will still pass through up the inheritance chain.
Docs: undef_method and remove_method
Use the undef keyword.
class A
def foo
5
end
end
class B < A
undef foo
end
A.new.foo #=> 5
B.new.foo #=> NameError: undefined local variable or method `foo'
That is wrong OOP that you're trying to do there. I suggest you use composition instead of inheritance.
require 'forwardable'
class SomeBaseClass
def foo
puts 'foo'
end
def bar
puts 'bar'
end
def quux
puts 'quux'
end
end
class MyClass
def initialize
#base = SomeBaseClass.new
end
extend Forwardable
def_delegators :#base, :foo, :bar # but not quux
end
mc = MyClass.new
mc.foo
mc.bar
mc.quux
# >> foo
# >> bar
# ~> -:32:in `<main>': undefined method `quux' for #<MyClass:0x007febcc155210> (NoMethodError)

Class-objects, singleton classes

I play with metaprogramming in ruby and I have a question. I have a class:
class Klass
class << self
#x = "yeah"
end
end
b = Klass.new
a = class << Klass; self; end
a.instance_eval "#x" #=> yeah
Klass.instance_eval "#x" #=> nil
Why? In variable a I have a singleton class, right? And Klass.instance_eval exec in context of a singleton class:
Klass.instance_eval "def yeah; puts 10; end"
Klass.yeah #=> 10
Also, Klass in interpreter points to context of class, yes? And a points to context of a singleton class?
And which indicates a.class_eval and a.instance_eval? I do:
a.instance_eval "def pops; puts 0; end"
a.class_eval "def popsx; puts 1; end"
a.pops #=> 0
a.popsx # FAIL
Klass.pops # FAIL
Klass.popsx #=> 1
b.pops; b.popsx # DOUBLE FAIL
and I do not understand this. Thanks!
First, while it seems like eigentclass is used by some people singleton class is more common term. Singleton class contains object-specific behavior for an object in Ruby. You can't create other instances of that class except the original object this singleton class belongs to.
Speaking about defining of methods inside different types of eval this article introduces nice rule for methods defined in instance_eval and class_eval:
Use ClassName.instance_eval to define class methods.
Use ClassName.class_eval to define instance methods.
That pretty much describes the situation.
There was a huge write-up about classes that are instances of Class class, their singleton classes that are subclasses of Class class and some other crazy stuff (not that much related to the problem). But as your question can be easily applied to regular objects and their classes (and it makes things much easier to explain), I decided to remove that all (though, you can still see that stuff in revisions history of the answer).
Let's look at regular class and instance of that class and see how that all works:
class A; end
a = A.new
Method definitions inside different types of eval:
# define instance method inside class context
A.class_eval { def bar; 'bar'; end }
puts a.bar # => bar
puts A.new.bar # => bar
# class_eval is equivalent to re-opening the class
class A
def bar2; 'bar2'; end
end
puts a.bar2 # => bar2
puts A.new.bar2 # => bar2
Defining object-specific methods:
# define object-specific method in the context of object itself
a.instance_eval { def foo; 'foo'; end }
puts a.foo # => foo
# method definition inside instance_eval is equivalent to this
def a.foo2; 'foo2'; end
puts a.foo2 # => foo2
# no foo method here
# puts A.new.foo # => undefined method `foo' for #<A:0x8b35b20>
Let's now look at singleton class of object a:
# singleton class of a is subclass of A
p (class << a; self; end).ancestors
# => [A, Object, Kernel, BasicObject]
# define instance method inside a's singleton class context
class << a
def foobar; 'foobar'; end;
end
puts a.foobar # => foobar
# as expected foobar is not available for other instances of class A
# because it's instance method of a's singleton class and a is the only
# instance of that class
# puts A.new.foobar # => undefined method `foobar' for #<A:0x8b35b20>
# same for equivalent class_eval version
(class << a; self; end).class_eval do
def foobar2; 'foobar2'; end;
end
puts a.foobar2 # => foobar2
# no foobar2 here as well
# puts A.new.foobar2 # => undefined method `foobar2' for #<A:0x8b35b20>
Now let's look at instance variables:
# define instance variable for object a
a.instance_eval { #x = 1 }
# we can access that #x using same instance_eval
puts a.instance_eval { #x } # => 1
# or via convenient instance_variable_get method
puts a.instance_variable_get(:#x) # => 1
And now to instance variables inside class_eval:
# class_eval is instance method of Module class
# so it's not available for object a
# a.class_eval { } # => undefined method `class_eval' for #<A:0x8fbaa74>
# instance variable definition works the same inside
# class_eval and instance_eval
A.instance_eval { #y = 1 }
A.class_eval { #z = 1 }
# both variables belong to A class itself
p A.instance_variables # => [:#y, :#z]
# instance variables can be accessed in both ways as well
puts A.instance_eval { #y } # => 1
puts A.class_eval { #z } # => 1
# no instance_variables here
p A.new.instance_variables # => []
Now if you replace class A with class Class and object a with object Klass (that in this particular situation is nothing more than instance of class Class) I hope you'll get explanation to your questions. If you still have some feel free to ask.
It's hard to completely answer your question (for a thorough explanation of Ruby's class model, look at Dave Thomas' excellent presentation), nevertheless:
With class_eval, you actually define instance methods - it's as if you were inside the body of the class. For example:
class Klass
end
Klass.class_eval do
def instance_method
puts 'instance method'
end
end
obj = Klass.new
obj.instance_method # instance method
With instance_eval, you actually define class methods - it's as if you were inside the body of the singleton (eigenclass) class of the given object (nota bene that classes are objects too in Ruby). For example:
Klass.instance_eval do
def class_method
puts 'class method'
end
end
Klass.class_method # class method
And in your case:
Klass.instance_eval "#x" does not work because #x is not part of Klass, it's part of Klass' singleton class:
class Klass
class << self
#x = "yeah"
end
puts #x
end
# prints nothing
a.instance_eval "#x" works fine because you evaluate "#x" in the context of the a singleton class that is connected with the singleton class of Klass class in which you defined the #x instance variable. How singleton classes can be interconnected can be illustrated by this example:
class Foo
end
f = class << Foo; self; end
g = class << Foo; self; end
f.instance_eval "def yeah; puts 'yeah'; end"
g.yeah # yeah
g.instance_eval "def ghee; puts 'ghee'; end"
f.ghee # ghee
Klass.instance_eval "def yeah; puts 10; end" defines a 'normal' class method. Therefore Klass.yeah works fine (see Klass.class_method in the previous example).
a.instance_eval "def pops; puts 0; end" defines a class method on the a singleton class. Therefore, a.pops actually means calling the pops class method (again, it's as if calling Klass.class_method).
a.popsx does not work because you would first have to create an instance of a to be able to call popsx on it (but is not possible to create a new instance of a singleton class).
Klass.pops does not work because there isn't any pops method defined in Klass' singleton class (pops is defined in a's singleton class).
Klass.popsx works because with a.class_eval "def popsx; puts 1; end" you have defined the popsx instance method which you then call on the Klass object. It is, in a way, similar to this example:
class Other
end
o = Other.new
Other.class_eval "def yeah; puts 'yeah'; end"
o.yeah # yeah
Hope it helps.

Ruby Class Methods vs. Methods in Eigenclasses

Are class methods and methods in the eigenclass (or metaclass) of that class just two ways to define one thing?
Otherwise, what are the differences?
class X
# class method
def self.a
"a"
end
# eigenclass method
class << self
def b
"b"
end
end
end
Do X.a and X.b behave differently in any way?
I recognize that I can overwrite or alias class methods by opening the eigenclass:
irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"
The two methods are equivalent. The 'eigenclass' version is helpful for using the attr_* methods, for example:
class Foo
#instances = []
class << self;
attr_reader :instances
end
def initialize
self.class.instances << self
end
end
2.times{ Foo.new }
p Foo.instances
#=> [#<Foo:0x2a3f020>, #<Foo:0x2a1a5c0>]
You can also use define_singleton_method to create methods on the class:
Foo.define_singleton_method :bim do "bam!" end
In Ruby there really are no such things as class methods. Since everything is an object in Ruby (including classes), when you say def self.class_method, you are just really defining a singleton method on the instance of the class Class. So to answer your question, saying
class X
def self.a
puts "Hi"
end
class << self
def b
puts "there"
end
end
end
X.a # => Hi
X.b # => there
is two ways of saying the same thing. Both these methods are just singeton (eigen, meta, ghost, or whatever you want to call them) methods defined in the instance of your Class object, which in your example was X. This topic is part of metaprogramming, which is a fun topic, that if you have been using Ruby for a while, you should check out.
The Pragmatic Programmers have a great book on metaprogramming that you should definitely take a look at if you interested in the topic.
Yet another necromancer here to unearth this old question... One thing you might not be aware of is that marking a class method as private (using the private keyword instead of :private_class_method) is different than marking an eigenclass method as such. :
class Foo
class << self
def baz
puts "Eigenclass public method."
end
private
def qux
puts "Private method on eigenclass."
end
end
private
def self.bar
puts "Private class method."
end
end
Foo.bar
#=> Private class method.
Foo.baz
#=> Eigenclass public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
# from (irb)
The following example will work how the previous one intends:
class Foo
class << self
def baz
puts "Eigen class public method."
end
private
def qux
puts "Private method on eigenclass."
end
end
def bar
puts "Private class method."
end
private_class_method :bar
end
Foo.bar
#=> NoMethodError: private method `bar' called for Foo:Class
# from (irb)
Foo.baz
#=> Eigen class public method.
Foo.qux
#=> NoMethodError: private method `qux' called for Foo:Class
# from (irb)
Most instance methods used in Ruby are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.
There is an apparent contradiction. Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.
If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.
class Zen
end
z1 = Zen.new
z2 = Zen.new
def z1.say_hello # Notice that the method name is prefixed with the object name
puts "Hello!"
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
In the above example, the say_hello method was defined within the z1 instance of the Zen class but not the z2 instance.
The following example shows a different way to define a singleton method, with the same result.
class Zen
end
z1 = Zen.new
z2 = Zen.new
class << z1
def say_hello
puts "Hello!"
end
end
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
In the above example, class << z1 changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.
Both of the above examples serve to illustrate how singleton methods work. There is, however, an easier way to define a singleton method: using a built-in method called define_singleton_method.
class Zen
end
z1 = Zen.new
z2 = Zen.new
z1.define_singleton_method(:say_hello) { puts "Hello!" }
z1.say_hello # Output: Hello!
z2.say_hello # Output: NoMethodError: undefined method `say_hello'…
We learned earlier that classes are also objects (instances of the built-in class called Class). We also learned about class methods. Class methods are nothing more than singleton methods associated with a class object.
One more example:
class Zabuton
class << self
def stuff
puts "Stuffing zabuton…"
end
end
end
All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method.
Read more at this post about Ruby Classes.

Resources