Undef - Why Would You Want to Undefine a Method in Ruby

undef - Why would you want to undefine a method in ruby?

There's also the blank class pattern in Ruby that needs the undef functionality.

The idea is to strip every method from your new class so that every call you make to it ends in #method_missing. That way you can implement a real proxy that just shuffles everything through. Implementing the decorator pattern with this is around ten lines of code, no matter how big your target class is.

If you want to see that idiom in action look at one of Ruby's mocking frameworks, they use it alot. Something like flexmock.

Another example is when you add functions dynamicly onto a class based on some condition. In a game you might add an #attack method onto the player object and then take it away when he´s paralyzed instead of doing it with a boolean flag. That way the calling class can check for the availabty of the method and not the flag. I´m not saying that this is a good idea, just that it´s made possible and there are far smarter people then me coming up with useful stuff to do with this.

When to use undef_method, and when to use remove_method?

From the fine manual:

undef_method(symbol) → self

Prevents the current class from responding to calls to the named method. Contrast this with remove_method, which deletes the method from the particular class; Ruby will still search superclasses and mixed-in modules for a possible receiver.

So a remove_method like this:

class CC < C
remove_method :m
end

is essentially the opposite of this:

class CC < C
def m
end
end

Where def m adds the method m to the class, remove_method :m removes m. But, if the super class has an m method, then that will still be used.

undef_method, OTOH, is more like this:

class CC < C
def m
raise 'No, you cannot do that.'
end
end

So undef_method doesn't actually remove the method, it replaces the method with a special internal flag that causes Ruby to complain if you try to call that method.

Sounds like you're trying to replace an existing method and replace is semantically the same as a remove followed by an add so remove_method is probably more appropriate. However, if you want to be paranoid and make sure the replacement method is in place, then undef_method would be useful; or, if for some reason you need to remove the method in one place and add it in another, undef_method would at least tell you that you only did half the job whereas remove_method would either leave you with the super class's implementation (and possible strange bugs) or a rather confusing NoMethodError.

Remove/undef a class method


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.

practical use for undef

I can only say that I've never had a use for it in 5 years. Perhaps more usefully, grepping through the entire source of rails shows only 7 instances and they're all meta-programming related. (undef_method has rather more instances at 22). It appears to be useful for testing the behaviour of classes with and without modules mixed-in.

Hopefully someone can point out some more conventional uses for it.

EDIT
See this previous question: undef - Why would you want to undefine a method in ruby?

How can I solve undefined method `[]' on Ruby?

When the input is invalid, the call to

@breweries_hash = HTTParty.get("...")

returns not the object you expect (I’d suggest it returns an empty hash.) That makes it impossible to get to details in the following lines. Depending on how are you to handle it, you might decide to e. g. early return from this function, or raise, or do something else.

To approach this, start with debugging the issue, like this:

@breweries_hash = HTTParty.get("...")
puts @breweries_hash.inspect
...

That way you’ll see what gets returned and get the ideas of how to handle it.

If I am right, and what is returned is an empty hash, you might want to early return from this function.

@breweries_hash = HTTParty.get("...")
return if @breweries_hash.empty?
...

What is the undef object of Ruby?

This is an educated guess on my part, maybe Matz will see this question at some point and give us a definitive answer, hopefully this will do in the meantime.

As you might know, ruby was somewhat influenced by perl at least early on (which is why we have variables like $@ and $_ etc.). Perl has an undef keyword/function (e.g. if you declare a variable without initialising - its value is undefined). I would say, that at some time in the past Ruby was also meant to have something similar (i.e. variables would be able to have an undefined value). How do we know this? By the context in which it is found.

As you can see, that comment describes how the object_id of the various Ruby objects is derived. Some details on that can be found here. But, in essence we know the following:

false.object_id == 0
true.object_id == 2
nil.object_id == 4

This is what the comment suggests and this is indeed the case, you can crack open an irb session and try it out for yourself. It looks like undef was meant to have an object_id of 6.

Now, undef is indeed a reserved word in Ruby, but it is not a special object like nil, false and true, it is - as we know - a keyword used to undefine a method.

So, to answer your question, there is no undef object, it has no class and you can't access it. The purpose that undef was meant to serve is instead being served by the nil object in the Ruby that we know today. But, it has remained in the code as a legacy of times gone by, for the more curious of us to find and puzzle over.

in `_main': undefined method `run' for nil:NilClass (NoMethodError)

At the point where you call request.run the value for request is nil. This is why you are seeing the error you're given.

This is happening because the line right above it assigns the nil value to the request variable.

You are clearly coming from another language that is not Ruby (some type of C maybe?), by how you've formatted things. It would help for you to get more familiar with Ruby and its idioms. However, best I can tell, you want to do something like this instead:

def _main
request = MySqliteRequest.new
request.from('nba_player_data.csv')
request.select('name')
request.where('birth_state', 'Indiana')
request.run
end
_main()

This assumes you've also defined (and in some cases probably overridden) these methods on your MySqliteRequest Object or Model:

from

select

where

However, please note that the way you're going about this is just completely against how Ruby and Ruby on Rails is designed to work.

+ is an undefined method after using super to call parent variables


I get an error: person.rb:31: undefined method `+' for nil:NilClass (NoMethodError). I understand that this error has the answer, but I am not yet adept at understanding what this means.

It means that one of the three variables is nil, i.e., it lacks a value:

m.first_name
m.last_name

This is occurring because you are returning the result of calling the puts function in all of your accessors. You need to return the variables themselves, not print them and return the result of the print function.

Also, since you are already using attr_reader you have get methods created for you already. That's the whole point of using attr_reader; it creates a function which returns an underlying instance variable for you, you simply need to initialize it.

for example, this:

class Foo
def bar
@bar
end
end

is equivalent to

class Foo
attr_reader :bar
end

Rails error : undefined method `product' for # User:0x00007faaa8c42700 Did you mean? products products=

You have left behind an old validation in your user model.

Delete this line in the app/models/user.rb file
validates_length_of :product, maximum: 10

what do an undefined method [] mean in rails?

See how you have 3 consecutive lines of nothing but code in your view? That's a sign you should pull it out into a helper, in order to keep your views clean.

New view code:

<%=h @contact.date_entered.to_date %></br>  
Next event: <%= next_delayed_todo(@contact) %> </br>

Then in your helper:

def next_delayed_todo(contact)
contact.next_delayed_todo[:event].title rescue ""
end

Note that the error you were getting is because of next_delayed_todo being nil. The first line of the helper method uses rescue "" to set an alternate value if it is nil. You can replace it with rescue "none." or any other string that makes sense.



Related Topics



Leave a reply



Submit