缓存具有(命名)范围的类时出错

发布于 2024-12-29 12:52:44 字数 857 浏览 0 评论 0原文

这是一个复杂的示例,所以请耐心等待:

我有一个在开发期间经常使用的脚本,它将清除我的开发和测试数据库的表,重新迁移,然后重新播种它们。由于我在几个地方使用了触发器,我不得不使用 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 是我的第一个范围定义和爆炸的地方我上面列出的。

This is a convoluted example so bear with me:

I have a script that I routinely use during dev that will wipe out my tables of my dev and test databases, remigrate, then reseed them. Due to my use of triggers in a couple places, I've had to use rake db:migrate RAILS_ENV=test to migrate my test database properly.

Everything was fine until I turned config.cache_classes=true on in my test environment. Then when the rake migration ran on an empty database I would get an error about how the table doesn't exist. Running this with a --trace, I find that its blowing up on one of my objects when it declares a basic scope:

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

The scope is in a lambda, so it shouldn't be getting evaluated, but the minute I remove cache_classes, the migration works fine. So, to me it seems like its trying to cache the model, choking on the scope because the table doesn't exist yet, and never starting the migration.

Am I losing my mind? Anyone else seen this? If I need to wipe my db, do I need to turn caching off, then migrate, then turn it back on?

Rails 3.2, ruby 1.9.2, rake 0.9.2.2

UPDATED:

As requested, here is the stack trace: https://gist.github.com/1705064

The order.rb:179 is the place where my first scope is defined and where it blows up that I listed above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云裳 2025-01-05 12:52:44

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

这会导致活动记录向下响应 respond_to ,它认为您的作用域/方法名称看起来很像动态查找器。然后它更进一步:除了看起来像动态查找器之外,所有命名属性都存在吗?这是它尝试检查不存在的表有哪些列的地方,然后一切都会崩溃。

您可以(我认为)执行以下操作之一:

  • 在作用域之前,定义一个与作用域同名的类方法,以便短路 respond_to 调用(恶心)
  • 更改您的作用域名称
  • 覆盖 valid_scope_name

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

This is interesting. My reading of the stack trace is that rails is trying to help you be seeing if whether creating that scope (ie creating a method of the same name) you would be creating trouble by overwriting some existing method.

This leads active record down respond_to where it thinks that your scope/method name looks a lot like a dynamic finder. It then goes further: as well as looking like a dynamic finder, do all the named attributes exist? This is where it tries to check what columns the non existant table has and everything blows up.

You could (I think) do one of a few things:

  • before the scope, define a class method with the same name as the scope so as to short circuit the respond_to call (yuck)
  • change your scope name
  • override valid_scope_name

I'm still not sure why you can't setup the test db from a schema file, if necessary setting the schema dumper to :sql so that things that active record doesn't support natively are preserved.

踏雪无痕 2025-01-05 12:52:44

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

最佳实践是始终使用更底层的方法来操作数据,无论 app/models 目录的状态如何,这些方法都可以正常工作。一个好的迁移套件可以从原始状态构建到最新版本,而不会因丢失文件或方法而陷入困境。这就是为什么自给自足很重要。

您可能可以将此范围重写为可以使用 execute 运行的更字面意义的东西。

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

Generally you shouldn't reference models at all in your migrations for a number of reasons. The most notable is that a lot of information about the table structure is cached when the model is instantiated the first time. The second most important issue is that the model file may not even exist in a future version of your app if it's refactored away.

A best practice is to always use more low-level methods of manipulating your data that will work regardless of the state of your app/models directory. A good migration suite can build from a pristine state to the most current version without getting hung up on missing files or methods. This is why being self-contained is important.

You can probably re-write this scope as a more literal thing that can be run with execute.

If you're using triggers and having trouble with the test environment because the schema dumper is not properly recording them, use the :sql format for your schema instead. This is a more literal copy and shouldn't be affected by the limitations of the Ruby-ized format.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文