samayres1992
samayres1992

Reputation: 779

Can't convert symbol to integer from hash table

Edit: The issue is being unable to get the quantity of arrays within the hash, so it can be, x = amount of arrays. so it can be used as function.each_index{|x| code }

Trying to use the index of the amount of rows as a way of repeating an action X amount of times depending on how much data is pulled from a CSV file.

Terminal issued

=> Can't convert symbol to integer (TypeError)

Complete error:

=> ~/home/tests/Product.rb:30:in '[]' can't convert symbol into integer (TypeError) from ~home/tests/Product.rub:30:in 'getNumbRel'
from test.rb:36:in '<main>'

the function is that is performing the action is:

def getNumRel
  if defined? @releaseHashTable
     return @releaseHashTable[:releasename].length
  else
      @releaseHashTable = readReleaseCSV()
      return @releaseHashTable[:releasename].length
  end
end

The csv data pull is just a hash of arrays, nothing snazzy.

def readReleaseCSV()
   $log.info("Method "+"#{self.class.name}"+"."+"#{__method__}"+" has started")
   $log.debug("reading product csv file")
   # Create a Hash where the default is an empty Array
   result = Array.new
   csvPath = "#{File.dirname(__FILE__)}"+"/../../data/addingProdRelProjIterTestSuite/releaseCSVdata.csv"
   CSV.foreach(csvPath, :headers => true, :header_converters => :symbol) do |row|
     row.each do |column, value|
       if "#{column}" == "prodid"
         proHash = Hash.new { |h, k| h[k] = [ ] }
         proHash['relid'] << row[:relid]
         proHash['releasename'] << row[:releasename]
         proHash['inheritcomponents'] << row[:inheritcomponents]

         productId = Integer(value)
         if result[productId] == nil
            result[productId] = Array.new
         end

         result[productId][result[productId].length] = proHash
      end
    end
  end
  $log.info("Method "+"#{self.class.name}"+"."+"#{__method__}"+" has finished")
  @productReleaseArr = result
 end

Upvotes: 2

Views: 1638

Answers (3)

Mark Thomas
Mark Thomas

Reputation: 37517

You haven't given much to go on, but it appears that @releaseHashTable contains an Array, not a Hash.

Update: Based on the implementation you posted, you can see that productId is an integer and that the return value of readReleaseCSV() is an array.

In order to get the releasename you want, you have to do this:

@releaseHashTable[productId][n][:releasename]

where productId and n are integers. Either you'll have to specify them specifically, or (if you don't know n) you'll have to introduce a loop to collect all the releasenames for all the products of a particular productId.

Upvotes: 2

Michiel de Mare
Michiel de Mare

Reputation: 42420

Sorry, couldn't resist, cleaned up your method.

# empty brackets unnecessary, no uppercase in method names
def read_release_csv
  # you don't need + here
  $log.info("Method #{self.class.name}.#{__method__} has started")
  $log.debug("reading product csv file")
  # you're returning this array. It is not a hash. [] is preferred over Array.new
  result = []
  csvPath = "#{File.dirname(__FILE__)}/../../data/addingProdRelProjIterTestSuite/releaseCSVdata.csv"
  CSV.foreach(csvPath, :headers => true, :header_converters => :symbol) do |row|
    row.each do |column, value|
      # to_s is preferred
      if column.to_s == "prodid"
        proHash = Hash.new { |h, k| h[k] = [ ] }
        proHash['relid'] << row[:relid]
        proHash['releasename'] << row[:releasename]
        proHash['inheritcomponents'] << row[:inheritcomponents]
        # to_i is preferred
        productId = value.to_i
        # this notation is preferred
        result[productId] ||= []
        # this is identical to what you did and more readable
        result[productId] << proHash
      end
    end
  end
  $log.info("Method #{self.class.name}.#{__method__} has finished")
  @productReleaseArr = result
end

Upvotes: 2

krichard
krichard

Reputation: 3694

This is what Mark Thomas meant:

> a = [1,2,3] # => [1, 2, 3] 
> a[:sym]
TypeError: can't convert Symbol into Integer
# here starts the backstrace
    from (irb):2:in `[]'
    from (irb):2

An Array is only accessible by an index like so a[1] this fetches the second element from the array
Your return a an array and thats why your code fails:

#....
result = Array.new
#....
@productReleaseArr = result
# and then later on you call
@releaseHashTable = readReleaseCSV()
@releaseHashTable[:releasename] # which gives you TypeError: can't convert Symbol into Integer

Upvotes: 1

Related Questions