【发布时间】:2014-06-24 16:47:47
【问题描述】:
我有以下 ActiveRecord 模型,Widget、Merchant、Store、StoresWidget(多对多关联)
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
所以对应的表是widgets、merchants、stores和stores_widgets,其中widgets和stores各有一个id列,stores_widgets有两列store_id和widget_id。一个小部件可以在 1 个或多个商店中使用,并且一个商店可以有许多可用的小部件。某些小部件在所有商店中都可用,有些仅在部分商店中可用。如果 Widget 仅限于商店的子集,则 restricted 列是 true
向商家添加新商店时,我想更新与该商店关联的所有不受限制的小部件。理想情况下,我希望在我的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
update_all_unrestricted_widgets_with_store 最终执行的 SQL 如下:
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)
因此,如果商家有 100000 个不受限制的小部件,则在一个 INSERT 中创建 100000 个新的 stores_widgets 行,而不是 100000 个不同的 INSERT。
最好我想让 ActiveRecord 构建这样的插入。那可能吗?如果不是,我可以用 ARel 做到这一点吗?如果可能的话,我想避免执行 SQL 字符串来实现这一点,这样我就可以在代码和数据库 SQL 语法之间保持一个级别。
【问题讨论】:
标签: ruby-on-rails activerecord ruby-on-rails-3.2 arel