我有 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 操作提交。
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 倍。这是解决这个问题的好方法吗?交易肯定不是为此设计的吗?从具有超过一千个条目的文件创建记录的其他选项是什么?