更新 has_many/belong_to 关系中的大量关联对象行(Rails 4,postgresql 9.4,activeadmin)
Update massive number of rows of associated objects in has_many/belong_to relations (Rails 4, postgresql 9.4, activeadmin)
创建模型交易时,我使用 after_create 在 DealPrize table 上创建奖品。
Deal和DealPrize有属于to/has_many的关系:一个Deal有多个Deal奖品,一个Dealprize属于一个Deal。
它是这样工作的:在我的管理面板上(使用 activeadmin),在一个 Deal 中,我有一列 'prize-number' 并且我使用了一个 after_create 这样每次管理员创建一个新的deal,应用程序使用此 prize_number 列,并在 DealPrize table.
中创建此数量的奖品(根据需要插入尽可能多的行 => 通常超过 300,000)
所以我创建了一个 Deal,然后应用程序自动创建了大量关联对象(奖品),比如 300,000 个。
问题是我可能希望 2 天后将奖品数量从 300,000 更改为 272,000(例如,较少奖品)或 324,000(更多奖品)。
如何在不删除并重新创建整个 Deal 对象的情况下更新创建的 Deal 并告诉我的 Rails 应用程序更新相关奖品的数量(删除一些或添加一些)?
另外,我需要一种快速的方法(比如我用来创建 Deal => raw sql 和 transaction 的方法,因为一次创建的行数非常多)。
模态 Deals.rb
has_many :deal_prizes, dependent: :delete_all
after_create :create_deal_prizes
CONNECTION = ActiveRecord::Base.connection.raw_connection
def create_deal_prizes
begin
CONNECTION.describe_prepared('yokoatxz')
rescue PG::InvalidSqlStatementName
CONNECTION.prepare('yokoatxz', 'INSERT INTO deal_prizes (deal_id,created_at,updated_at,admin_user_id) values (, , , )')
end
Deal.transaction do
self.prizes_number.times do |i|
CONNECTION.exec_prepared('yokoatxz', [ { value: self.id},
{ value: '2009-01-23 20:21:13' },
{ value: '2009-01-23 20:21:13' },
{ value: self.admin_user_id }
] )
end
end
end
谢谢你的帮助,马修
好吧,我认为如果您只想更改 deal_prizes 的数量,那么您可以在 Deal 上使用 before_save 回调来测试 prize_number 和 prize_number_was,并适当地发出插入或删除语句。
我希望您可以执行以下操作:
deal_prizes.limit(prize_number_was - prize_number).delete_all
...如果您不在乎哪些已被删除。
您可能希望在 deal_prizes:
上使用范围
def self.deletable
where(:taken => false)
end
...应用可以删除行的条件,然后将其合并到交易关联中...
has_many :deletable_deal_prizes, -> {merge(DealPrize.deletable)}, :class_name => "DealPrize"
...这样您就可以:
deleteable_deal_prizes.limit(prize_number_was - prize_number).delete_all
创建模型交易时,我使用 after_create 在 DealPrize table 上创建奖品。
Deal和DealPrize有属于to/has_many的关系:一个Deal有多个Deal奖品,一个Dealprize属于一个Deal。
它是这样工作的:在我的管理面板上(使用 activeadmin),在一个 Deal 中,我有一列 'prize-number' 并且我使用了一个 after_create 这样每次管理员创建一个新的deal,应用程序使用此 prize_number 列,并在 DealPrize table.
中创建此数量的奖品(根据需要插入尽可能多的行 => 通常超过 300,000)所以我创建了一个 Deal,然后应用程序自动创建了大量关联对象(奖品),比如 300,000 个。
问题是我可能希望 2 天后将奖品数量从 300,000 更改为 272,000(例如,较少奖品)或 324,000(更多奖品)。
如何在不删除并重新创建整个 Deal 对象的情况下更新创建的 Deal 并告诉我的 Rails 应用程序更新相关奖品的数量(删除一些或添加一些)?
另外,我需要一种快速的方法(比如我用来创建 Deal => raw sql 和 transaction 的方法,因为一次创建的行数非常多)。
模态 Deals.rb
has_many :deal_prizes, dependent: :delete_all
after_create :create_deal_prizes
CONNECTION = ActiveRecord::Base.connection.raw_connection
def create_deal_prizes
begin
CONNECTION.describe_prepared('yokoatxz')
rescue PG::InvalidSqlStatementName
CONNECTION.prepare('yokoatxz', 'INSERT INTO deal_prizes (deal_id,created_at,updated_at,admin_user_id) values (, , , )')
end
Deal.transaction do
self.prizes_number.times do |i|
CONNECTION.exec_prepared('yokoatxz', [ { value: self.id},
{ value: '2009-01-23 20:21:13' },
{ value: '2009-01-23 20:21:13' },
{ value: self.admin_user_id }
] )
end
end
end
谢谢你的帮助,马修
好吧,我认为如果您只想更改 deal_prizes 的数量,那么您可以在 Deal 上使用 before_save 回调来测试 prize_number 和 prize_number_was,并适当地发出插入或删除语句。
我希望您可以执行以下操作:
deal_prizes.limit(prize_number_was - prize_number).delete_all
...如果您不在乎哪些已被删除。
您可能希望在 deal_prizes:
上使用范围def self.deletable
where(:taken => false)
end
...应用可以删除行的条件,然后将其合并到交易关联中...
has_many :deletable_deal_prizes, -> {merge(DealPrize.deletable)}, :class_name => "DealPrize"
...这样您就可以:
deleteable_deal_prizes.limit(prize_number_was - prize_number).delete_all