[英]How to insert all the nested attributes in bulk using rails active record
我有這樣的報告 model :-
class Report < ActiveRecord::Base
has_many :report_clients
accepts_nested_attributes_for :report_clients, :reject_if => proc { |attributes| attributes['client_id'].blank? }, :allow_destroy => true
end
而報告客戶端 model 就像
class ReportClient < ActiveRecord::Base
belongs_to :report
end
在創建報告時,我的參數結構將類似於
Report.create({name: params[:name], report_clients_attributes: [{client_id: 1}, {client_id:2}]})
它將運行 1 個查詢以插入報告和 2 個查詢以插入 report_clients。
通常,我曾經針對每個報告插入 1000 個 report_clients,這會導致 1000 個 sql 查詢。
我知道,我可以通過編寫原始 sql 插入來解決使用批量插入的問題。 但想知道是否有任何其他方式/更好的方式來做到這一點。
經歷過類似的情況后,對於此類情況,有一個很棒的gem activerecord-import 。
report = Report.new(name: params[:name])
report.save_with_nested_attributes(report_clients_attributes)
在report.rb
def save_with_nested_attributes(report_clients_attributes)
report_clients_objects = []
transaction do
save!
report_clients_attributes.each do |client_attributes|
report_clients_objects << report_clients.new(client_attributes)
end
ReportClient.import(report_clients_objects)
end
end
gem Wiki中提到了許多其他方式來批量導入記錄。
希望有幫助!
正如我在這篇博文中更詳細地概述的那樣,您可以使用模型的autosave_associated_records_for_#{relation}
方法的覆蓋來批量插入嵌套屬性。
class Report < ActiveRecord::Base
has_many :report_clients
accepts_nested_attributes_for :report_clients,
allow_destroy: true,
reject_if: :blank?
def autosave_associated_records_for_report_clients
return if report_clients.empty?
ReportClient.insert_all(
report_clients.map { |r| { report_id: id, client_id: r.client_id } },
record_timestamps: true,
)
end
end
默認情況下,這只會在:create
上運行,但如果您將autosave: true
添加到關系中,也可以用於:update
。 雖然您需要處理標記為marked_for_destruction?
, 並相應地刪除它們,否則它將是僅插入的。 您可能還想查看upsert_all
,因為可以更新或跳過重復項。
另一件需要注意的是 model 驗證——它們不是用insert_all
運行的。 記在腦子里。 您可能能夠手動運行 model 驗證,但批量插入最好與強大的數據庫約束一起使用。
最后——這是使用內部(即私有)Rails API,但它在 9 年內沒有改變。
您可以如下使用create
Report.create({name: params[:name], report_clients: report_clients})
其中report_clients定義為
def report_clients
clients = [{client_id: 1}, {client_id:2}]
clients.map do |client|
ReportClient.new(client)
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.