codyc4321
codyc4321

Reputation: 9682

how to solve NoMethodError efficiently (rails)?

I am new to rails and notice a very odd pattern. I thought some error messages in Django were obscenely cryptic, but building my second app in rails I notice my errors come up NoMethodError more than 90% of the time.

How do rails people tell the difference between all these errors with the same name?

What does NoMethodError mean at it's core? It seems like what you're calling in the template is misspelled, or you're accessing attributes that don't exist?

Where can this error happen? Is the only possible cause in the template/view (the html.erb file)? Or can a bad call in the controller and whatnot cause same error?

Also, what is the best debugger gem to alleviate these issues? Reading the full trace isn't too helpful for beginners at least for a while, I;d like a first hand account of what debugger someone uses instead of reading hype

Thank you kindly

Upvotes: 0

Views: 118

Answers (3)

fylooi
fylooi

Reputation: 3870

This is not a Rails specific error actually. I'll try to explain what's happening at its core.

Ruby is a language that functions through message passing. Objects communicate by sending messages to each other.

The message needs to be defined as a method on the object to respond to it. This can be directly defined on the object itself, the object's class, the object's class's parents/ancestors or through included modules.

class MyObject
  def some_method
    puts "Yay!"
  end
end

> MyObject.new.some_method
Yay!

Objects can define method_missing to handle unexpected messages.

class MyObject
  def method_missing(name, *args, &block)
    puts name
  end
end

> MyObject.new.some_undefined_method
some_undefined_method

Without the method_missing handler, the object will raise a NoMethodError

class MyObject
end

> MyObject.new.some_undefined_method
NoMethodError: undefined method 'some_undefined_method' for #<MyObject...>

So what does this look like in Rails?

$ rails generate model User name:string

Produces this

# models/user.rb
class User < ActiveRecord::Base
end

Which has the following methods implemented among others (by ActiveRecord)

  def name
  end

  def name=(value)
  end

When you do the following:

# create a new User object
> user = User.new 
#<User ... >

# call the 'name=' method on the User object
> user.name = "name" 
"name"

# call the 'name' method on the User object. Note that these are 2 different methods
> user.name
"name" 

> user.some_undefined_method
NoMethodError: undefined method 'some_undefined_method' for #<User...>

You'll see the same results whether you're calling it in your console, your model, your controller or in the view as they're all running the same Ruby code.

ERB view templates are slightly different in that what you enter is only evaluated as Ruby code when it's between <% %> or <%= %>. Otherwise, it gets written out to the page as text.

Upvotes: 0

ilan berci
ilan berci

Reputation: 3881

How do rails people tell the difference between all these errors with the same name?

We usually look at the stack trace that comes back with the response (in development mode) as well as looking in the logs. In a dev environment, I am running my server in a console where I can scroll through the request.

What does NoMethodError mean at it's core? It seems like what you're calling in the template is misspelled, or you're accessing attributes that don't exist?

Due to dynamic coupling nature of Ruby. When Ruby determines that an object doesn't have a method by the name of the one that was called. It looks for a method by the name of "method_missing" within that object. If it's not defined then the super one is called which has the default behaviour of raising an exception. Rails leverages this mechanism heavily in it's internal dispatching

Where can this error happen? Is the only possible cause in the template/view (the html.erb file)? Or can a bad call in the controller and whatnot cause same error?

This error can happen wherever you have Ruby code, It has nothing to do with rails

Also, what is the best debugger gem to alleviate these issues? Reading the full trace isn't too helpful for beginners at least for a while, I;d like a first hand account of what debugger someone uses instead of reading hype

An Invaluable tool for debugging is the gem 'pry'. It has many useful plug-able tools that greatly simplify debugging

Upvotes: 0

Simone Carletti
Simone Carletti

Reputation: 176562

NoMethodError means you are calling a method on an object, but that object doesn't provide such method.

This is a quite bad error in the sense that is reveals a poorly designed and tested application. It generally means your code is not behaving as you are expected.

The way to reduce such errors is:

  • Make sure that when you are writing the code you are taking care of the various edge cases that may happen, not just the correct path. In other words, you need to take care of validating what's going on and making sure that if something is not successful (e.g. the user is not supplying all the input requested) your application will handle the case gracefully.
  • Make sure you write automatic test cases that covers the behavior of each method in your codebase
  • Keep track of the errors. When an error occurs, write a test to reproduce the behavior, fix the code and check the test passes. That will reduce the risk of regression.

Upvotes: 1

Related Questions