Array of hashes - Nil class error

I have reorganized my input log data to below structure and trying to export as a excel spreadsheet. I'm facing below issue while pushing values to excel sheet and I have checked array for any nil class but the result is false and I'm not sure where is the issue.

final = [ {:server=>"new_US_dof1_new"}
{:name=>"OLAUS51", :data=>{"HAL"=>"6.93817139", "CCN_RESP"=>".035400391", "PA_RESP"=>".032287598", "PE_RESP"=>".000610352"}}
{:name=>"OLAUS10", :data=>{"HAL"=>"52.7266846", "CFG_RESP"=>"15.9489746"}}
{:name=>"IdofQA03", :data=>{"PA_RESP"=>".096374512"}}
{:name=>"QEMDB", :data=>{"HAL"=>"22.2698975", "PA_RESP"=>"11.7857666", "CCN_RESP"=>".229125977", "PE_RESP"=>".007202148"}}
{:name=>"OLAUS64", :data=>{"CCN_RESP"=>".757202148"}}
{:name=>"IISCR70", :data=>{}}
{:name=>"IQDV500", :data=>{}}
{:name=>"OLAUS80", :data=>{"PA_RESP"=>"10.5393066", "HAL"=>"4.73620605", "CCN_RESP"=>".023864746", "PE_RESP"=>".003723145", "OPENREPORTS"=>".001708984", "REPORT_RESP"=>".001281738"}}

{:server=>"new_US_dof2_new"}
{:name=>"IBDVHAL", :data=>{"HAL"=>"1.81048584", "FM_RESP"=>".001098633"}}
{:name=>"DEVSITEP", :data=>{"HAL"=>".088012695", "PE_RESP"=>".000610352"}}
{:name=>"OLAUS87", :data=>{"CFG_RESP"=>"1.57061768", "HAL"=>".47253418", "PA_RESP"=>".011962891", "PE_RESP"=>".007202148"}}

same format for other servers]

Error:

in `block (2 levels) in <main>': undefined method `each' for nil:NilClass (NoMethodError)
        from excel.rb:34:in `each'
        from excel.rb:34:in `block in <main>'
        from C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/axlsx-2.0.1/lib/axlsx/workbook/workbook.rb:262:in `add_worksheet'

I'm trying to format the data in excel sheet of below format

SERVER               NAME         DATA         GB

new_US_dof1_new"     OLAUS51      HAL          6.93817139
                                  CCN_RESP     .035400391
                                  PA_RESP      .032287598
                                  PE_RESP      000610352

                     OLAUS10      HAL           52.7266846
                                  CFG_RESP      15.9489746       

Likewise for other NAME & SERVER

The code I've come up with

require 'csv'
require 'axlsx'

final = []
current = -1

str = File.read("combined.log")
str.each_line do |line|
  line.strip!
  next if line.empty?
  next if line.include?('selected') || line.include?('IN_GB')
  next if ['-','='].include? line[0]
  parts = line.split ' '
   if parts.size == 1 and line.start_with?('size')
    final[current += 1] = {server: line.strip}
    next
  elsif parts.size == 1 and parts = /^(?!.*size_).*$/
    final[current += 1] = {name: line, data: {}}
    next
  end

  parts.each_cons(2) do |key, value|
    final[current][:data][key] = value 
    end
end

#puts final

p = Axlsx::Package.new

wb = p.workbook
wb.add_worksheet(:name => "Basic") do |sheet|
    sheet.add_row ["SERVER", "NAME", "DATA", "GB]"]
    final.each do |val|
      sheet << [ val[:server], val[:name] ]
      val[:data].each do |k, v|
       sheet << ["", "", k, v]
      end
    end
end

p.serialize 'server.xlsx'

Posting the portion of the log file for reference:

---- db name ----
new_US_dof1_new

OLAUS51


RESP                    IN_GB
------------------------------ ----------
HAL                6.93817139
CCN_RESP               .035400391
PA_RESP            .032287598
PE_RESP            .000610352


=========================================


---- db name ----


OLAUS10


RESP                    IN_GB
------------------------------ ----------
HAL                52.7266846
CFG_RESP               15.9489746
CCN_RESP               .401794434
PA_RESP            .346679688
PE_RESP            .008056641


=========================================
I"m skipping the values for server 1 & proceeding to server 2 values for better readability 

---- db name ----
new_US_dof2_new

IBDVHAL

RESP                    IN_GB
------------------------------ ----------
HAL                1.81048584
FM_RESP           .001098633

=========================================


---- db name ----

DEVSITEP

RESP                    IN_GB
------------------------------ ----------
HAL                088012695
FM_RESP           .000610352

and so on for other server and values

1 answer

  • answered 2018-07-12 10:45 Leo

    in `block (2 levels) in <main>': undefined method `each' for nil:NilClass (NoMethodError)
    

    That means error happens inside block from line 34(2 levels). So, val[:data].each do |k, v|. Your first hash from final array is {:server=>"new_US_dof1_new"} that haven't key :data.

    final.each_with_object do |val, line|
      line << val.key?(:server) ? val[:server] : ''
      line << val[:name]
    
      val[:data].each do |k, v|
        line << k << v
        sheet << line
        line.clear
        line << '' << ''
      end
      line.clear
    end