控制器对延迟工作的行动

时间:2012-10-18 14:10:11

标签: ruby-on-rails ruby-on-rails-3 background-process

我正在上传制表符分隔的文档并在控制器中处理。一切正常,但可能需要一些时间在一个大文件上。我想把它移到delay_job,我已经在我的应用程序的其他地方工作了,但是因为这是在控制器中,所以不能以相同的方式调用。

表单调用process_file操作,该操作又调用salesupload操作。我应该如何将其转变为后台工作?

class SalesController < ApplicationController

  def salesupload(file)
    uploaded_io = file.read
    numrows = "uploaded_io.size"
    FasterCSV.parse(uploaded_io, {:headers => true, :col_sep =>"\t"}).each do |row_data|
        full, upc, _discard, isrc = row_data[26].match(/^([^_]+)(_(.+))?/).to_a
          new_record = AppleSale.new(
              'provider' =>  row_data[0],
              'provider_country' => row_data[1],
              'vendor_identifier' => row_data[2]
          )
      new_record.save
    end
  end

    def process_file
        file = params[:apple_sale][:tsv_file]
        salesupload(file)
    end

end

3 个答案:

答案 0 :(得分:9)

我发现当我必须这样做时,控制器中定义的方法必须是类方法。我不记得为什么会这样,我认为这与拥有更明确的接收器有关。所以我要做的是使salesupload方法成为一个类方法,然后只需在其上调用.delay

def self.salesupload(files)
  # code
end

def process_file
  file = params[:apple_sale][:tsv_file]
  SalesController.delay.salesupload(file)
  head :no_content
end

你应该好好去!我也通过AJAX调用了我的原始方法(在这种情况下为process_file),然后我附加了head :no_content,以便它返回一些东西而不需要重定向或任何东西。

答案 1 :(得分:2)

我写了一个名为delayed_action的宝石来做这件事。

在这种情况下,你要写 delayed_action [:sales_upload]

那就是它。

答案 2 :(得分:1)

我想你应该把这段代码移到一个模型或一个单独的类中(例如在lib文件夹中)。但这只是组织和最佳实践的问题。

关于在后台运行此代码,您有很多选择。 如果你想使用delayed_job我猜你应该看这个截屏视频:   http://railscasts.com/episodes/171-delayed-job

但基本上,在设置延迟作业后,您只需使用send_later(:process_file)之类的东西来告诉在后台运行该项目。 它非常简单,您的命令和数据结构将保存在数据库表中,之后分离的进程可以执行它。我想在看完轨道广播之后你会得到你的答案;)