Reputation: 226
I have the following ActiveRecord models, Widget, Merchant, Store, StoresWidget (many-to-many association)
class Merchant < ActiveRecord::Base
has_many :stores
has_many :widgets
end
class Widget < ActiveRecord::Base
has_many :stores_widgets
has_many :stores, :through => :stores_widgets
belongs_to :merchant
end
class Store < ActiveRecord::Base
has_many :stores_widgets
has_many :widgets, :through => :stores_widgets
belongs_to :merchant
end
class StoresWidget < ActiveRecord::Base
belongs_to :widget
belongs_to :store
end
So the corresponding tables are widgets
, merchants
, stores
and stores_widgets
, where widgets
and stores
each has a id
column and stores_widgets
has two columns store_id
and widget_id
. A Widget can be available in 1 or more stores and a store can have many widgets available. Some widgets are available in all stores some are only available in a sub-set of stores. If a Widget is restricted to a subset of stores, the column restricted
is true
When a new store is added to a merchant I want to update all the unrestricted widgets to be associated with that store. Ideally I would like to have code like this in my StoresController#create
class StoresController < ApplicationController
def create
# build new store...
Store.transaction do
store.save!
Widget.update_all_unrestricted_widgets_with_store(store)
end
render :show
end
end
Where update_all_unrestricted_widgets_with_store
ends up executing SQL like:
INSERT INTO stores_widgets (store_id, widget_id)
(SELECT #{store.id}, widgets.id
FROM widgets
WHERE widgets.merchant_id = #{store.merchant_id}
AND widgets.restricted = FALSE)
So if a merchant has 100000 widgets that are unrestricted a 100000 new stores_widgets rows are created in one INSERT rather than 100000 distinct INSERTS.
Preferably I would like to get ActiveRecord to build an insert like this. Is that possible? If not would I be able to do this with ARel? I want to avoid executing a SQL string to achieve this if possible, so that I can maintain a level if separation between the code and the database SQL syntax.
Upvotes: 2
Views: 2382
Reputation: 340
You can use activerecord-import implements AR#import
activerecord-import is a library for bulk inserting data using ActiveRecord.
see how it works:
books = []
10.times do |i|
books << Book.new(:name => "book #{i}")
end
Book.import books
Reference - https://github.com/zdennis/activerecord-import
Upvotes: 2