简体   繁体   中英

Ruby resque background CSV import does not run

I am trying to import a CSV file using a background job with resque. It appears to run but nothing happens. The import worked fine when I was not using resque (I am using resque because some imports are large and I want to move to a background job, for testing its a small 2 row csv)

Any help is super appreciated, thank you very much! (also im a beginner so please dumb down any help :))

inventories_controller.rb :

  def import
    Resque.enqueue(Inventorycsvimport, params[:file], current_user.id)
    redirect_to root_url, notice: "Inventory import job started."
  end

worker JOB inventorycsvimport.rb :

class Inventorycsvimport
  @queue = :Inventorycsvimport
  def self.perform()
    Inventory.destroy_all(user_id: current_user.id)
    Inventory.import(params[:file], current_user.id)
  end
end

Import Class inventory.rb :

class Inventory < ApplicationRecord
    belongs_to :user

  def self.import(file, user_id)
    allowed_attributes = [ "user_id", "id","description","part_number","price","created_at","updated_at", "alternate_part_number", "condition_code", "qty", "mfg_code", "serial_number", "part_comments"]
    spreadsheet = open_spreadsheet(file)
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).each do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      inventory = find_by_id(row["id"]) || new
      inventory.attributes = row.to_hash.select { |k,v| allowed_attributes.include? k }
      inventory.user_id = user_id
      inventory.save!
    end
  end

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

This is the error I get in the JOB:

在此处输入图片说明

I advise you to check Sidekiq documentation. As far as I know, all passed in parameters are available inside the job through options hash. so when passing parameter you need to receive it on the other end somehow.

Try this in controller:

  def import
    Resque.enqueue(Inventorycsvimport, file: params[:file], user_id: current_user.id)
    redirect_to root_url, notice: "Inventory import job started."
  end

and this in your job:

  def self.perform
    Inventory.destroy_all(user_id: options[:user_id])
    Inventory.import(options[:file], options[:user_id])
  end

Your code does not make a lot of sense (I advise some programming tutorials (codecademy.com could be a good start), because you are trying to use variables in different scopes. The current_user that you have in your controller is not a magical variable that you can access anywhere. It comes from helper methods defined under ActionController::Base or ApplicationController classes from which your controller class inherits.

Since your Job classes have nothing to do with the controller classes, it can't access any of controller's methods or variables directly. Thus you have such options as parameters when defining methods, which allows you to pass these variables across different classes and scopes.

What might be confusing in this case is the job's perform method, where you do not have to declare options as an argument, because it is using ActiveJob (or plain Sidekiq ) class under the hood which has the same method with options hash defined as an argument. the file: and user_id: are just a pretty thing in Ruby called named arguments . So you do not have to constantly check the parameter order, when using a function. But srsly, I suggest taking some tutorials and you will get this in no time :)

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