【问题标题】:Rails update_counters error with default_scope带有 default_scope 的 Rails update_counters 错误
【发布时间】:2013-07-05 18:12:27
【问题描述】:

我正在添加一个 counter_cache,但我的迁移出错了。

def up
    add_column :benefits, :benefit_rows_count, :integer, :default => 0

    Benefit.reset_column_information
    Benefit.find(:all).each do |b|
      Benefit.update_counters b.id, :benefit_rows_count => b.benefit_rows.length
    end
end

SQL:

UPDATE "benefits" SET "benefit_rows_count" = COALESCE("benefit_rows_count", 0) + 0 
WHERE "benefits"."id" IN (SELECT "benefits"."id" 
    FROM "benefits"
    WHERE "benefits"."id" = 1 
    ORDER BY benefit_types.position, benefit_types.name, id)

更新里面的这个ORDER BY,是因为default_scope,迁移失败。

不幸的是,当我更新记录时,在执行回调 update_counters 时我得到了同样的错误。我读过一些帖子说应该避免使用 default_scope。我检查了 Rails 4 源代码(我使用的是 Rails 3)并且 update_counters 尚未修复。我将重新打开 ActiveRecord::CounterCache.update_counters 并尝试取消其范围。

【问题讨论】:

标签: ruby-on-rails migrate


【解决方案1】:

如前所述,您的默认范围会让您感到困惑。有一种更好的方法可以在迁移中避免此类问题:在迁移范围内重新定义模型:

class MigrateFooToBar < ActiveRecord::Migration

  class Foo < ActiveRecord::Base; end

  def up
    # ...
  end
end

然后,当您从 up 中引用 Foo 时,您引用的是 void-of-restrictions-and-default-scopes MigrateFooToBar::Foo,这会使您从 A) 迁移到必须了解太多关于您的模型和 B)当团队中的其他人运行您的迁移时,他们会感到困惑。

【讨论】:

  • 目前,我不会使用 default_scope。这个项目是由其他程序员启动的,但我冒昧地更改了命名范围的 default_scopes。
【解决方案2】:

谢谢 Baldrick,我是 Rails 新手。并且无范围的工作:

Benefit.unscoped.update_counters b.id, :benefit_rows_count => b.benefit_rows.length

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-03
    • 2010-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多