本文介绍了“方法缺失"的模型Rails 4 中的行为与 Rails 3 不同(可能导致“堆栈级别太深"错误)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在 Rails 3.2.14 上运行良好的 Rails 应用程序.我刚刚开始将它升级到 Rails 4,主要是跟随 Railscast 第 415 集.

I have a Rails application that was working fine with Rails 3.2.14. I have just started to work on upgrading it to Rails 4, essentially following along with Railscast episode 415.

我尝试运行我的 rspec 测试以发现许多现在失败并出现以下错误的部分:

I got as far as the part where I try to run my rspec tests to find many now fail with the following error:

 Failure/Error: Unable to find matching line from backtrace
 SystemStackError:
   stack level too deep

我还检查了我的 Cucumber 测试并发现了类似的失败.

I also checked my Cucumber tests and find similar failures.

stack level too deep (SystemStackError)

因为在我开始升级之前一切都很好,所以我一直在寻找其他类似但没有找到的体验.

As everything was fine before I started upgrading, I have been searching for other experiences that are similar but haven't found any.

我尝试过 Ruby 1.9 和 2.0.我没有修改任何代码

I have tried both Ruby 1.9 and 2.0. I have not modified any code

感谢任何指导.

更新:

我已将问题追溯到一个模型,该模型将 method_missing 作为其实现的一部分.我已经在单独的答案中描述了我发现的内容,以便可以单独评论.

I have tracked the problem down to a model thatat defines method_missing as part of its implementation. I have described what I have found in a separate answer so that it can be commented on separately.

我的应用程序包含一个模型,该模型实现了自己的 method_missing,这可能导致递归循环,最终导致堆栈级别到深度"错误.

My application contained a model that implemented its own method_missing which could cause a recursive loop that ultimatly concluded in the "stack level to deep" error.

推荐答案

根据建议,有足够的细节来保证将其作为答案分开.

Per suggestion, there is sufficient detail to warrant separating this as an answer.

我已将问题追溯到一个模型,该模型将 method_missing 定义为实现的一部分.我发现,如果模型中有 method_missing 定义,那么它被称为而不是任何访问器.这会导致任何模型设置失败.

I have tracked the problem down to a model that defines method_missing as part of its implementation. I have found that, if there is a method_missing definition in the model, then it is called instead of any accessors. This causes any model set-up to fail.

(在我的特定情况下,method_missing 被定义,这就是我最初提到的堆栈溢出的原因).

(in my specific case, method_missing was defined and this is what caused the stack overflow that I mentioned originally).

我可以通过在 Rails 3.2.14 中定义一个新的 Rails 应用程序然后创建一个新模型来简洁地重现该问题:

I can reproduce the problem succinctly by defining a new rails app in Rails 3.2.14 and then creating a new model:

class Item < ActiveRecord::Base
  attr_accessible :name, :content
  store :content

  def method_missing(id, *args)
    puts "method missing: #{id}"
  end
end

以及相关的迁移

class CreateItems < ActiveRecord::Migration
  def change
    create_table :items do |t|
      t.string :name
      t.text :content

      t.timestamps
    end
  end
end

如果我运行 Rails 控制台,我可以练习模型:

If I run a rails console I can exercise the model:

$ rails console
Loading development environment (Rails 3.2.14)
2.0.0p247 :001 > x = Item.new(name: 'foo')
 => #<Item id: nil, name: "foo", content: {}, created_at: nil, updated_at: nil>
2.0.0p247 :002 >

如果我在 Rails 4.0.0 中构建完全相同的东西,我会得到不同的输出:

If I build exactly the same thing in Rails 4.0.0 I get different output:

$ rails console
Loading development environment (Rails 4.0.0)
2.0.0p247 :001 > x = Item.new(name: 'foo')
method missing: name=
 => #<Item id: nil, name: nil, content: {}, created_at: nil, updated_at: nil>
2.0.0p247 :002 >

您会注意到,在 Rails 3.2.14 中,name 属性被设置为 foo,这也是本意.但是,在 Rails 4.0.0 中,会看到调用了 method_missing 并且未设置属性.

You'll notice that, in Rails 3.2.14, the name attribute is set to foo as is the intention. In Rails 4.0.0, however, see that method_missing is called and the attribute is not set.

我正在阅读对 ActiveRecord 的更改,但我找不到任何表明使用 method_missing 的模型在 Rails 4 之前还可以在 Rails 4 中不再适用的任何内容.

I am reading up on the changes to ActiveRecord but I haven't been able to find anything that suggests models using method_missing which were ok prior to Rails 4 would no longer be ok in Rails 4.

让代码示例能够在 Rails 4 中工作的任何指示都将帮助我解决我的模型遇到的问题.

Any pointers to getting the code example able to work in Rails 4 would help me solve the problems that I have with my model.

更新

通过手动调用向上的method_missing链,我可以让上面的例子工作:

By manually invoking the upward method_missing chain, I can get the above example to work:

  def method_missing(id, *args)
    super
    if respond_to? id
      send(id,*args)
    else
      puts "method missing: #{id}"
    end
  end

需要这样做对我来说是错误的,因为不清楚为什么这种行为在 Rails 3 和 4 之间发生了变化.我觉得我错过了其他东西......

Needing to do this feels wrong to me because it isn't clear why this behaviour changed between Rails 3 and 4. I feel I am missing something else...

这篇关于“方法缺失"的模型Rails 4 中的行为与 Rails 3 不同(可能导致“堆栈级别太深"错误)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-24 11:58