Reputation: 1050
I want to clone a list of ActiveRecord
objects in an optimized way. Maybe the way that I am using is optimized already but I need to speed up this process. So this is my code
ActiveRecord::Base.transaction do
data = MyModel.where(column_1: 'x')
data.each do |item|
new_item = item.dup
new_item.column_2 = 'y'
new_item.save!
end
end
Maybe there is a better way of duplicating a list of records at once then update all of them with one query. I tried to Google it but no luck till now.
Upvotes: 0
Views: 732
Reputation: 1740
If you want to do this as quickly as possible then SQL is the way to go.
Something like this would do it:
ActiveRecord::Base.connection.execute <<-SQL
INSERT INTO my_models (column_1, column_2, column_3, ..)
SELECT column_1, 'y', column_3, ..
FROM my_models WHERE column_1 = 'x';
SQL
This should work in PostgreSQL and MySql.
If you have any rails magic columns (created_at, updated_at etc) they will have to be added manually in the SQL.
Upvotes: 0
Reputation: 1050
Short answer is to use single insert statement
instead of multiple inserts
even though if it's in one DB transaction
.
And bulk_insert gem will help you to do it. ( Thanks to arieljuod )
Upvotes: 0
Reputation: 2052
If I understood right, you want to duplicate objects that meet condition
(column_1: 'x')
You can try this approach, looks like it will do the same
MyModel.where(column_1: 'x').find_each { |u| u.dup.update(column2: 'y') }
But a little slower(benchmarked n = 1000)
<Benchmark::Tms:0x00007f96e6a1b970 @label="**dup.update**", @real=6.75463099999979, @cstime=0.0, @cutime=0.0, @stime=0.331546, @utime=2.2468139999999996, @total=2.5783599999999995>,
<Benchmark::Tms:0x00007f96e8cb23f8 @label="**dup.save!**", @real=6.470054999999775, @cstime=0.0, @cutime=0.0, @stime=0.32828900000000005, @utime=1.972385, @total=2.300674>
Upvotes: 1