次のような EventsController create アクションがあります。
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
この問題の解決策を 1 つ見つけました。コントローラー作成アクションを ActiveRecord::Base.transaction にラップします。
class EventsController < ApplicationController
around_filter :transactions_filter, only: [:create]
def transactions_filter
ActiveRecord::Base.transaction do
yield
end
end
end
このソリューションが機能している間、トランザクションは 1 つだけ作成され、プロセス全体が約 60 倍高速化されます。この問題に取り組む良い方法ですか?? 確かにトランザクションはこれのために設計されていませんか?? 1000 を超えるエントリを持つファイルからレコードを作成するための他のオプションは何ですか??