2012-01-27 88 views
1

这是一个令人费解的例子如此忍受我:错误(命名)作用域

我有一个脚本,我开发过程中经常使用,这将消灭我的我的开发和测试数据库的表,重新迁移,然后再种上它们。由于我在几个地方使用了触发器,我不得不使用rake db:migrate RAILS_ENV = test来正确地迁移我的测试数据库。

一切都很好,直到我把我的测试环境中的config.cache_classes = true。然后,当耙子迁移运行在空数据库上时,我会得到一个关于该表不存在的错误。与--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,红宝石1.9.2,耙0.9.2.2

更新:

按照要求,这里是堆栈跟踪:https://gist.github.com/1705064

的order.rb:179是放置我的第一个范围的地方,以及我上面列出的爆炸点。

+0

你得到了什么栈跟踪? – phoet 2012-01-27 23:15:10

+0

编辑包含链接到要点的痕迹 – 2012-01-30 15:49:47

+0

我觉得有点奇怪'order_controller.rb'在堆栈中。确定你没有在你的耙子任务中做一些疯狂的事情,那实际上是调用范围? – phoet 2012-01-30 18:10:06

回答

2

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

这导致活动记录下降respond_to它认为您的范围/方法名称看起来很像动态查找程序。然后进一步:像动态查找器一样,所有命名属性都存在吗?这是它试图检查不存在的表有什么列,并且所有东西都炸了。

你可以(我认为)做的几件事情之一:

  • 范围之前,定义一个类方法具有相同名称的范围,从而短路的respond_to调用(呸)
  • 更改范围名
  • 覆盖valid_scope_name

我仍然不知道为什么你不能设置从模式文件中的测试数据库,如果有必要的架构自卸车设置为:sql以便保留活动记录本身不支持的内容。

+0

你死了。我将范围重命名为看起来不像寻找器,并且迁移运行良好。我会研究SQL翻车机,这对我的触发器来说是一个更好的解决方案。谢谢! – 2012-01-30 19:27:26

0

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

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

您或许可以将此作用域重新编写为可以使用execute运行的更为直接的事情。

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

+0

我的迁移不是指模型。这是在迁移完成之前发生的。 – 2012-01-30 19:20:11

+1

从我收集的模型没有被用于迁移(虽然我同意这很危险) – 2012-01-30 19:23:48

+0

那很奇怪。看起来你有一个修复,但! – tadman 2012-01-30 20:57:50