【问题标题】:Update massive number of rows of associated objects in has_many/belong_to relations (Rails 4, postgresql 9.4, activeadmin)更新 has_many/belong_to 关系中的大量关联对象行(Rails 4、postgresql 9.4、activeadmin)
【发布时间】:2015-09-13 18:47:25
【问题描述】:

创建模型 Deal 时,我使用 after_create 在 DealPrize 表上创建奖品。

Deal 和 DealPrize 有一个属于/has_many 关系:一个 Deal 有多个 Deal 奖品,而一个 Dealprize 属于一个 Deal。

它的工作原理是这样的:在我的管理面板上(使用 activeadmin),在 Deal 中,我有一个“prize-number”列,我使用了 after_create,这样每次管理员创建新交易时,应用程序都会使用这个Prize_number 列,并在 DealPrize 表中创建此数量的奖品(根据需要插入尽可能多的行 => 通常超过 300,000)。

所以我创建了一个 Deal,应用程序会自动创建大量相关对象(奖品),比如 300,000 个。

问题是我可能希望在 2 天后将奖品号码从 300,000 更改为 272,000(例如,减少奖品)或 324,000(更多奖品)。

如何在不删除和重新创建整个 Deal 对象的情况下更新已创建的 Deal 并告诉我的 Rails 应用更新相关奖品的数量(删除一些或添加一些)?

另外,我需要一种快速的方法(比如我用来创建 Deal => 原始 sql 和事务的方法,因为一次创建的行数非常多)。

模态 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 ($1, $2, $3, $4)') 
      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

感谢您的帮助,马修

【问题讨论】:

  • 除了插入和删除它们之外,您实际上对这些价格做了什么?
  • 在某些视图中需要它们。我需要 200K 行大约相似的“奖品”。不能只有 1 排奖品,数字 = 200K。所以每次我创建一个交易时,我都会告诉 Rails 创建 340,000 个相关奖品。现在创建和删除都可以。唯一的问题是当我想更新奖品数量时(在 Deal 表的 Prize_number 列内)。例如,如果我弄错了号码,或者即使计划发生了变化。
  • 你不会展示这些奖品吧?
  • 我创建、更新和删除它们:仅在更改 Deal 内的内容时创建、更新或删除它们。就好像他们完全依赖于我在 Deal 中的 Prize_number 列上所做的事情,或者如果我删除了 Deal,那么它们也必须被删除。
  • 我会在视图中使用它们,是的,但不是一次全部使用:)

标签: ruby-on-rails ruby ruby-on-rails-3 postgresql activeadmin


【解决方案1】:

好吧,我认为如果您只是想更改 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

【讨论】:

  • 会尝试这样的事情。如果我从 300K 变为 330K(更多奖品),我将不得不提供。
  • 现在必须去,但明天会尝试,如果有效,将验证答案。再次感谢您的宝贵帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多