Dawn Green Dawn Green - 4 months ago 11
MySQL Question

How do I retrieve a list of created IDs for bulk insert in Active Record?

I have three models:

class Coupon < ActiveRecord::Base
belongs_to :event
has_many :coupon_events, :dependent => :destroy
has_many :events, :through => :coupon_events
end

class Event < ActiveRecord::Base
belongs_to :event
has_many :coupon_events, :dependent => :destroy
has_many :coupons, :through => :coupon_events
end

class CouponEvent < ActiveRecord::Base
belongs_to :coupon
belongs_to :event
end


I read through a CSV file to create coupons and coupon_events. This is terribly inefficient since the records are created one at a time and result in multiple queries each including the two insert statements.

I'd like to use a single insert query like this:

coupon_string = " ('abc','AAA'), ('123','BBB')"
Coupon.connection.insert("INSERT INTO coupons (code, name) VALUES"+coupon_string)


I then need to create the second insert query for the CouponEvent model, but I need a list of the returned coupon_ids. Is there a built in method to retrieve the IDs at the time of the insert?

Answer

If you are using mysql and you are not inserting more rows in another script/process, you can get the id of the first row inserted by using last_insert_id()

    first_id = ActiveRecord::Base.connection.execute("select last_insert_id()").first[0]

And then the ids of the other records are sequentially generated.

i.e.

    data = %w(one two three)
    to_insert = "('" + data.join("'), ('") + "')"
    Model.connection.insert("INSERT INTO models(name) VALUES #{to_insert}")
    first_id = ActiveRecord::Base.connection.execute("select last_insert_id()").first[0].to_i
    hash = {}
    data.each_with_index {|d, i| hash[first_id + i] = d}
Comments