Question

I used the Railscasts to create a feature for uploading CSV and Excel files. Importing CSV files is working well, but when I use Ryan's code for importing Excel sheets using the Roo gem, it throws an error:

TypeError in InventoryItemsController#import "can't convert nil into Hash"

Here is the import method in the controller:

def import 
  InventoryItem.import(params[:file])
  redirect_to inventory_items_path, notice: "Inventory Items imported successfully!"
end

I have require 'roo' in the application.rb file along with require 'csv'

The code in the model is:

def self.import(file)
  spreadsheet = open_spreadsheet(file)
  header = spreadsheet.row(1)
  (2..spreadsheet.last_row).each do |i|
    row = Hash[[header, spreadsheet.row(i)].transpose]
    inventory_item = InventoryItem.find_by_inventory_id(row["inventory_id"]) || new
    inventory_item.attributes = row.to_hash #.slice(*accessible_attributes)
    inventory_item.save!
  end
end

def self.open_spreadsheet(file)
  binding.pry
  case File.extname(file.original_filename)
  when ".csv" then CSV.new(file.path, nil)
  when ".xls" then Excel.new(file.path, nil)
  when ".xlsx" then Excelx.new(file.path, nil)
  else raise "Unknown file type: #{file.original_filename}"
  end
end

So, the point I'm stuck on is that the CSV file imports successfully with the following code:

  def self.import(file)
    CSV.foreach(file.path, headers: true) do |row|
      inventory_item = InventoryItem.find_by_inventory_id(row["inventory_id"]) || new
      inventory_item.attributes = row.to_hash #.slice(*accessible_attributes)
      inventory_item.save!
    end
  end

but it doesn't work when using the code from up above (self.import with self.open_spreadsheet).

This is using the Roo gem and I think that there is some rewriting to do in the methods but I'm not really sure... I'm stuck on what to do next to get this to work.

Any help would be much appreciated! Thank you!

Full trace of error:

TypeError (can't convert nil into Hash)
/Users/marcacyr/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/csv.rb:1565:in `merge'
/Users/marcacyr/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/csv.rb:1565:in `initialize'
app/models/inventory_item.rb:27:in `new'
app/models/inventory_item.rb:27:in `open_spreadsheet'
app/models/inventory_item.rb:14:in `import'
app/controllers/inventory_items_controller.rb:85:in `import'
actionpack (3.0.9) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
actionpack (3.0.9) lib/abstract_controller/base.rb:150:in `process_action'
actionpack (3.0.9) lib/action_controller/metal/rendering.rb:11:in `process_action'
actionpack (3.0.9) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
activesupport (3.0.9) lib/active_support/callbacks.rb:476:in `_run__2908593346646715497__process_action__1677791179652643815__callbacks'
activesupport (3.0.9) lib/active_support/callbacks.rb:410:in `_run_process_action_callbacks'
activesupport (3.0.9) lib/active_support/callbacks.rb:94:in `run_callbacks'
actionpack (3.0.9) lib/abstract_controller/callbacks.rb:17:in `process_action'
actionpack (3.0.9) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'
activesupport (3.0.9) lib/active_support/notifications.rb:52:in `block in instrument'
activesupport (3.0.9) lib/active_support/notifications/instrumenter.rb:21:in `instrument'
activesupport (3.0.9) lib/active_support/notifications.rb:52:in `instrument'
actionpack (3.0.9) lib/action_controller/metal/instrumentation.rb:29:in `process_action'
actionpack (3.0.9) lib/action_controller/metal/rescue.rb:17:in `process_action'
newrelic_rpm (3.6.1.88) lib/new_relic/agent/instrumentation/rails3/action_controller.rb:38:in `block in process_action'
newrelic_rpm (3.6.1.88) lib/new_relic/agent/instrumentation/controller_instrumentation.rb:318:in `perform_action_with_newrelic_trace'
newrelic_rpm (3.6.1.88) lib/new_relic/agent/instrumentation/rails3/action_controller.rb:37:in `process_action'
actionpack (3.0.9) lib/abstract_controller/base.rb:119:in `process'
actionpack (3.0.9) lib/abstract_controller/rendering.rb:41:in `process'
rack-mini-profiler (0.1.31) Ruby/lib/mini_profiler/profiling_methods.rb:108:in `block in profile_method'
actionpack (3.0.9) lib/action_controller/metal.rb:138:in `dispatch'
actionpack (3.0.9) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'
actionpack (3.0.9) lib/action_controller/metal.rb:178:in `block in action'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:62:in `call'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:62:in `dispatch'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:27:in `call'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:148:in `block in call'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:93:in `block in recognize'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:68:in `optimized_each'
rack-mount (0.6.14) lib/rack/mount/code_generation.rb:92:in `recognize'
rack-mount (0.6.14) lib/rack/mount/route_set.rb:139:in `call'
actionpack (3.0.9) lib/action_dispatch/routing/route_set.rb:493:in `call'
newrelic_rpm (3.6.1.88) lib/new_relic/rack/error_collector.rb:12:in `call'
newrelic_rpm (3.6.1.88) lib/new_relic/rack/agent_hooks.rb:18:in `call'
newrelic_rpm (3.6.1.88) lib/new_relic/rack/browser_monitoring.rb:16:in `call'
newrelic_rpm (3.6.1.88) lib/new_relic/rack/developer_mode.rb:28:in `call'
meta_request (0.2.7) lib/meta_request/middlewares/app_request_handler.rb:13:in `call'
rack-contrib (1.1.0) lib/rack/contrib/response_headers.rb:17:in `call'
meta_request (0.2.7) lib/meta_request/middlewares/headers.rb:16:in `call'
meta_request (0.2.7) lib/meta_request/middlewares/meta_request_handler.rb:13:in `call'
meta_request (0.2.7) lib/meta_request/middlewares/request_id.rb:24:in `call'
bullet (4.6.0) lib/bullet/rack.rb:10:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/head.rb:14:in `call'
rack (1.2.8) lib/rack/methodoverride.rb:24:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/params_parser.rb:21:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/flash.rb:182:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/session/abstract_store.rb:149:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/cookies.rb:302:in `call'
activerecord (3.0.9) lib/active_record/query_cache.rb:32:in `block in call'
activerecord (3.0.9) lib/active_record/connection_adapters/abstract/query_cache.rb:28:in `cache'
activerecord (3.0.9) lib/active_record/query_cache.rb:12:in `cache'
activerecord (3.0.9) lib/active_record/query_cache.rb:31:in `call'
activerecord (3.0.9) lib/active_record/connection_adapters/abstract/connection_pool.rb:354:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/callbacks.rb:46:in `block in call'
activesupport (3.0.9) lib/active_support/callbacks.rb:416:in `_run_call_callbacks'
actionpack (3.0.9) lib/action_dispatch/middleware/callbacks.rb:44:in `call'
rack (1.2.8) lib/rack/sendfile.rb:106:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/remote_ip.rb:48:in `call'
airbrake (3.1.12) lib/airbrake/rails/middleware.rb:13:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/show_exceptions.rb:47:in `call'
railties (3.0.9) lib/rails/rack/logger.rb:13:in `call'
rack (1.2.8) lib/rack/runtime.rb:17:in `call'
activesupport (3.0.9) lib/active_support/cache/strategy/local_cache.rb:72:in `call'
rack (1.2.8) lib/rack/lock.rb:13:in `block in call'
<internal:prelude>:10:in `synchronize'
rack (1.2.8) lib/rack/lock.rb:13:in `call'
actionpack (3.0.9) lib/action_dispatch/middleware/static.rb:30:in `call'
rack-mini-profiler (0.1.31) Ruby/lib/mini_profiler/profiler.rb:278:in `call'
airbrake (3.1.12) lib/airbrake/user_informer.rb:16:in `_call'
airbrake (3.1.12) lib/airbrake/user_informer.rb:12:in `call'
railties (3.0.9) lib/rails/application.rb:168:in `call'
railties (3.0.9) lib/rails/application.rb:77:in `method_missing'
railties (3.0.9) lib/rails/rack/log_tailer.rb:14:in `call'
rack (1.2.8) lib/rack/content_length.rb:13:in `call'
rack (1.2.8) lib/rack/handler/webrick.rb:52:in `service'
/Users/marcacyr/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'
/Users/marcacyr/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'
/Users/marcacyr/.rvm/rubies/ruby-1.9.3-p448/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'
Was it helpful?

Solution

The error is pointing to the place where you try to create a new CSV, and the error is telling you exactly what is wrong. It can't convert nil into a hash. Instead of CSV.new(file.path, nil) you should probably do CSV.new(file.path, {}) or CSV.new(file.path).

OTHER TIPS

For Rails 4 and Ruby 2, I have error "500 Internal Server Error" when follow Railscast #396

My solution now is use:

Roo::CSV.new(file.path, csv_options: {col_sep: ";"})

instead of

Csv.new(file.path, nil, :ignore)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top