Insert Bulk data using active record import
Imagine a scenario where you have to create a report and send it to multiple clients, so lets just say you have a report model and you have client and you have report client model.
Now it will run one single query to import all the report clients records
INSERT INTO report clients (...) VALUES
(...),
(...),
(...),
(...),
...
That's it :) . We have lots of customization option for the gem please take a look into their wiki page.
https://github.com/zdennis/activerecord-import/wiki
lets first check all the association and model structure.
#report model
class Report < ActiveRecord::Base
has_many :report_clients
has_many :clients, through: :report_clients
end
#report_client
class ReportClient < ActiveRecord::Base
belongs_to :report
belongs_to :client
end
#clients
class Client < ActiveRecord::Base
has_many :report_clients
has_many :reports, through: :report_clients
end
No lets say you want to create a report for 30 clients. You can do that by adding nested attributes in rails.
so our report model will became
class Report < ActiveRecord::Base
has_many :report_clients
has_many :clients, through: :report_clients
accepts_nested_attributes_for :report_clients, :reject_if => proc { |attributes| attributes['client_id'].blank? }, :allow_destroy => true
end
So using nested attributes we can directly save report and report_clients.
But the potential problem is if for one single report if we are trying to create 100 report_clients, Rails will generate 100 insert query for report_clients basically it will trigger N+1 query problem.
One alternative solutions for the problem is trying to insert all the clients in a single query, and for that we will gonna use activerecord-import gem (https://github.com/zdennis/activerecord-import)
By using the gem we can import all the associated records using one single query.
Steps to use the gem
1) Add the gem in your gem file
gem 'activerecord-import'
2) Now modify the save method
Instead of doing report.save
try to do something like
report.save_with_nested_attributes(report_clients_attributes)
3) In report model create a method
def save_with_nested_attributes(report_clients_attributes)
report_clients_objects = []
transaction do
if save
report_clients_attributes.each do |client_attributes|
report_clients_objects << report_clients.new(client_attributes)
end
end
ReportClient.import(report_clients_objects)
end
end
Steps to use the gem
1) Add the gem in your gem file
gem 'activerecord-import'
2) Now modify the save method
Instead of doing report.save
try to do something like
report.save_with_nested_attributes(report_clients_attributes)
3) In report model create a method
def save_with_nested_attributes(report_clients_attributes)
report_clients_objects = []
transaction do
if save
report_clients_attributes.each do |client_attributes|
report_clients_objects << report_clients.new(client_attributes)
end
end
ReportClient.import(report_clients_objects)
end
end
Now it will run one single query to import all the report clients records
INSERT INTO report clients (...) VALUES
(...),
(...),
(...),
(...),
...
That's it :) . We have lots of customization option for the gem please take a look into their wiki page.
https://github.com/zdennis/activerecord-import/wiki
very informative blog and useful article thank you for sharing with us , keep posting Ruby on Rails Online Training
ReplyDeleteThanks for sharing this blog post,Nice written skill selenium Online Training Hyderabad
ReplyDelete