Fikayo Olatunji Fikayo Olatunji - 2 months ago 12
Ruby Question

I an getting an "Undefined method 'new' for.... (A number that changes each time)"

I made a simple program with a single method and I'm trying to test it, but I keep getting this weird error, and I have no idea why it keeps happening.
Here's my code for the only method I wrote:

def make_database(lines)
i = 0
foods =
while i < lines.length do
lines[i] = lines[i].chomp()
words = lines[i].split(',')
if(words[1].casecmp("b") == 0)
foods[words[0]] = words[3]
return foods

And then here's what I have for calling the method (Inside the same program).

lines = []
$stdin.each { |line| lines << line}
foods = make_database(lines).new
puts foods

I am painfully confused, especially since it gives me a different random number for each "Undefined method 'new' for (Random number)".


It's a simple mistake. hash calls a method on the current object that returns a number used by the Hash structure for indexing entries, where Hash is the hash class you're probably intending:

foods =

Or more succinctly:

foods = { }

It's ideal to use { } in place of unless you need to specify things like defaults, as is the case with:

Where all values are initialized to 0 by default. This can be useful when creating simple counters.

Ruby classes are identified by leading capital letters to avoid confusion like this. Once you get used to the syntax you'll have an easier time spotting mistakes like that.

Note that when writing Ruby code you will almost always omit braces/brackets on empty argument lists. That is x() is expressed simply as x. This keeps code more readable, especially when chaining, like x.y.z instead of x().y().z()

Other things to note include being able to read in all lines with readlines instead of what you have there where you manually compose it. Try:


A more aggressive refactoring of your code looks like this:

def make_database(lines)
  # Define a Hash based on key/value pairs in an Array...
    # ...where these pairs are based on the input lines... do |line|
      # ...which have comma-separated components.
    end.reject do |key, flag, _, value|
      # Pick out only those that have the right flag.
      flag.downcase == 'b' do |key, flag, _, value|
      # Convert to a simple key/value pair array
      [ key, value ]

That might be a little hard to follow, but once you get the hang of chaining together a series of otherwise simple operations your Ruby code will be a lot more flexible and far easier to read.