我有一个如下所示的EventsController创建操作:
class EventsController < ApplicationController
def create
@event = Event.new(params[:event].slice(*Event.accessible_attributes))
if @event.save
DraftBuilder.new(event: @event).build(params[:event][:file].path)
redirect_to @event
else
render :new
end
end
end
params [:event] [:file] 是用户可以通过file_field_tag通过Event#new action提交的文件。
除了许多其他方面之外,DraftBuilder #build 方法解析给定文件并在数据库中创建大约1000条记录(将数据保存到多个表中的数据库中)。
我遇到的问题是DraftBuilder#build非常慢。它很慢,因为我在循环中保存记录,Active Record为每次保存创建新事务。
简化的DraftBuilder#build可能如下所示:
class DraftBuilder
def build(file)
@data = parse(file) #@data is an array of hashes with 1000+ records
@data.each do |pick_arguments|
Pick.create(pick_arguments)
end
end
end
我找到了解决这个问题的方法。包裹控制器在ActiveRecord :: Base.transaction中创建操作:
class EventsController < ApplicationController
around_filter :transactions_filter, only: [:create]
def transactions_filter
ActiveRecord::Base.transaction do
yield
end
end
end
虽然此解决方案正常运行,但只创建一个事务,并将整个过程加速约60次。这是解决这个问题的好方法吗?当然交易还没有为此设计?从包含超过一千个条目的文件创建记录的其他选项是什么?
答案 0 :(得分:3)
缓慢运行流程的最佳解决方案是使用delayed_job或resque或sidekiq等后台作业。
答案 1 :(得分:2)
您有两种方式:
而不是
@data.each do |pick_arguments|
Pick.create(pick_arguments)
end
1)交易
ActiveRecord::Base.transaction do
@data.each do |pick_arguments|
Pick.create(pick_arguments)
end
end
2)Gem activerecord-import
data = []
@data.each do |pick_arguments|
data << Pick.new(pick_arguments)
end
Pick.import books