1

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()
1
  • 1
    @transactions is being defined on the eigenclass TestRun, rather than instances of TestRun. Commented Jan 23, 2017 at 4:33

2 Answers 2

5

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
Sign up to request clarification or add additional context in comments.

1 Comment

The answer by @31piy has an incorrect wording and in general just blindly shows “how other people usually do it.” Thanks for putting this great explanation here. Upvoted, of course.
2

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

6 Comments

“The initialize method is used to initialize instance variables of a class.”—it might be used for that, but it’s initial purpose is far from this.
@mudasobwa Agreed. What I mentioned is one way to do it. Cary Swoveland's answer is much more explanatory.
@mudasobwa so, what is the initial purpose of initialize?
@Stefan to perform an initialization of an object, that might include but is not limited to instance variables settings. E.g. DbConnection singleton class might establish a connection to the database, and TestHelper might prepare the database content with fixtures. On the other hand, lazy getters are almost everywhere do better, than an initialization in initialize. I have a nifty proof of that thesis, but the margins here are too small to put it in :)
"The initialize method is used to initialize instance variables of a class." – No. It is used to initialize objects, not classes.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.