使用(命名)范围缓存类时出错

时间:2012-01-27 19:13:35

标签: ruby-on-rails rake

这是一个令人费解的例子,请耐心等待:

我有一个脚本,我在开发期间经常使用它将消除我的开发和测试数据库的表,重新启动,然后重新设置它们。由于我在几个地方使用了触发器,我不得不使用rake db:migrate RAILS_ENV = test来正确地迁移我的测试数据库。

在我的测试环境中将config.cache_classes = true打开之前,一切都很好。然后当rake迁移在空数据库上运行时,我会得到关于表不存在的错误。使用--trace运行它,我发现它在宣布基本范围时会炸毁我的一个对象:

scope :find_by_route_and_date, lambda { |route_id, date|
    {
      :conditions=>{:route_id=>route_id, :schedule_date=>date}
    }
  }

范围是lambda,因此不应该进行评估,但是当我删除cache_classes时,迁移工作正常。所以,对我而言,似乎它试图缓存模型,因为表尚不存在而窒息范围,并且从未开始迁移。

我是否会失去理智?有人见过这个吗?如果我需要擦除我的数据库,是否需要关闭缓存,然后迁移,然后重新打开?

Rails 3.2,ruby 1.9.2,rake 0.9.2.2

更新:

根据要求,这是堆栈跟踪:https://gist.github.com/1705064

order.rb:179是我定义第一个范围的位置,以及我在上面列出的范围。

2 个答案:

答案 0 :(得分:2)

这很有趣。我对堆栈跟踪的阅读是rails试图帮助您了解是否创建该范围(即创建一个相同名称的方法),您将通过覆盖一些现有方法来创建麻烦。

这导致活动记录向下respond_to,它认为您的范围/方法名称看起来很像动态查找器。然后它更进一步:看起来像一个动态查找器,是否存在所有命名属性?这是它试图检查非existant表有哪些列以及一切都爆炸的地方。

你可以(我认为)做以下几点之一:

    在范围之前
  • ,定义一个与范围同名的类方法,以便将respond_to调用短路(yuck)
  • 更改范围名称
  • 覆盖valid_scope_name

我仍然不确定为什么你不能从模式文件设置测试数据库,如果有必要,将模式转储器设置为:sql,以便保留活动记录本身不支持的内容。< / p>

答案 1 :(得分:0)

通常,出于多种原因,您不应在迁移中引用模型。最值得注意的是,在第一次实例化模型时,会缓存有关表结构的大量信息。第二个最重要的问题是模型文件可能在应用的未来版本中甚至不存在,如果它被重构的话。

最佳做法是始终使用更多低级操作数据的方法,无论app/models目录的状态如何,这些方法都能正常工作。一个好的迁移套件可以从原始状态构建到最新版本,而不会挂起丢失的文件或方法。这就是为什么自足是重要的。

您可以将此范围重写为可以使用execute运行的更直接的内容。

如果您正在使用触发器并且在test环境中遇到问题,因为架构转储器未正确记录它们,请改为使用架构的:sql格式。这是一个更文字的副本,不应受Ruby-ized格式的限制。