user4541806
user4541806

Reputation:

Ruby - Array of Hashes - Undefined method 'each' error

I'm wanting to iterate through the array of hashes and print the values to the terminal.

Currently receiving an error:

main.rb:14:in `print': undefined method `each' for nil:NilClass (NoMethodError)
from main.rb:22:in `<main>'

I'm wanting to iterate through, as opposed to something simple likeputs @transactions

Any ideas why I'm receiving this error? Thanks

class TestRun
   @transactions = [
      {:repayment_number => 1, :repayment_amount => 224.34},
      {:repayment_number => 2, :repayment_amount => 241.50},
      {:repayment_number => 3, :repayment_amount => 135.04},
      {:repayment_number => 4, :repayment_amount => 91.00}
   ]

   def print()
      @transactions.each do |t|
         puts "#{t[:repayment_number]} - #{t[:repayment_amount]}"
      end
   end

end

@test = TestRun.new
@test.print()

Upvotes: 1

Views: 1060

Answers (2)

Cary Swoveland
Cary Swoveland

Reputation: 110675

You have defined @transactions twice, initially when self equals TestRun, making it a class instance variable, then within the print method, when self is the instance TestRun.new, making that one an instance variable. Those two variables are as different as @night and @day.

Here are three ways to make your code work (the first two being for educational purposes only).

Make print a class method

class TestRun
  puts "self at class level = #{self}"
  @transactions = [
    {:repayment_number => 1, :repayment_amount => 224.34},
    {:repayment_number => 2, :repayment_amount => 241.50}
  ]
  def self.print
    puts "self within self.print = #{self}"
    @transactions.each do |t|
      puts "#{t[:repayment_number]} - #{t[:repayment_amount]}"
    end
  end
end
  #=> self at class level = TestRun
TestRun.print
  #=> self within self.print = TestRun
  #   1 - 224.34
  #   2 - 241.5

Access the class instance variable from within the method print

class TestRun
  @transactions = [
    {:repayment_number => 1, :repayment_amount => 224.34},
    {:repayment_number => 2, :repayment_amount => 241.50}
  ]
  def print
    puts "self within print = #{self}"
    self.class.instance_variable_get(:@transactions).each do |t|
      puts "#{t[:repayment_number]} - #{t[:repayment_amount]}"
    end
  end
end

TestRun.new.print
  #=> self within print = #<TestRun:0x007fcccb13f390>
  #   1 - 224.34
  #   2 - 241.5

Define @transactions within the initialize method, making it an instance variable

This is what @31piy has done, and most likely what is intended by the OP.

class TestRun
  def initialize
    puts "self within initialize = #{self}"    
    @transactions = [
      {:repayment_number => 1, :repayment_amount => 224.34},
      {:repayment_number => 2, :repayment_amount => 241.50}
    ]
  end
  def print
    puts "self within print = #{self}"
    @transactions.each do |t|
      puts "#{t[:repayment_number]} - #{t[:repayment_amount]}"
    end
  end
end

TestRun.new.print
  #=> self within initialize = #<TestRun:0x007fcccb2ae988>
  #   self within print = #<TestRun:0x007fcccb2ae988>
  #   1 - 224.34
  #   2 - 241.5

Upvotes: 5

31piy
31piy

Reputation: 23859

The @transactions is nil because it is not initialized as an instance variable. The initialize method can be used to create this when the class object is created.

You need to correct your code to leverage it.

class TestRun
   def initialize
     @transactions = [
       {:repayment_number => 1, :repayment_amount => 224.34},
       {:repayment_number => 2, :repayment_amount => 241.50},
       {:repayment_number => 3, :repayment_amount => 135.04},
       {:repayment_number => 4, :repayment_amount => 91.00}
     ]
   end

   def print()
      @transactions.each do |t|
         puts "#{t[:repayment_number]} - #{t[:repayment_amount]}"
      end
   end

end

@test = TestRun.new
@test.print()

Upvotes: 2

Related Questions