简体   繁体   中英

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 like puts @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()

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

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM