【问题标题】:Referencing an object that was declared before reload! in Rails console cause ArgumentError引用在重新加载之前声明的对象!在 Rails 控制台中导致 ArgumentError
【发布时间】:2017-07-17 03:19:46
【问题描述】:

Ruby 2.1.7 和 Rails 4.0.2

在使用 rails 控制台时。我已经看到如果我在控制台中声明一个对象。比调用重载!然后使用创建另一个类的实例的代码调用同一对象上的方法将引发错误:

ArgumentError:First 的副本已从模块树中删除,但仍处于活动状态!

一个例子更容易理解:

在我的应用程序/模型文件夹中,我向类声明:

app/models/first.rb

class First
  def foo
    Second.new
  end
end

app/models/second.rb

class Second
end

比我在控制台中运行的命令:

x = First.new
reload!
x.foo

我得到了例外

你能解释一下为什么会这样吗?使用在重新加载之前声明的引用是错误的吗?异常是一件好事,我不应该尝试找到解决方法,否则它表明我的代码或配置中有问题

我有这个问题:A copy of xxx has been removed from the module tree but is still active

一个解决方案是添加额外的 :: 作为前缀,如果我使用这个:

::Second.new

我没有得到异常

你认为使用这个解决方案是一件好事还是太hacky而不是Ruby Way?

你能解释一下为什么这不会导致错误吗?

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

    这是由于 Rails 自动加载缺少常量的方式。在您的示例中:
    1. 在使用“Second”时,Rails 首先假定它是“First”模块中的一个常量,为了防止使用过时的模块,它会检查名称为“First”的模块是否真的存在,因为“First”有尚未自动加载,它会引发异常。
    => 这是一件好事(在您的情况下,使用时 x 应该是已定义类的实例)
    2. 当使用“::Second”时,Rails 认为它​​是顶层常量,并且成功解析了“Second”常量。
    =>我认为这是一件坏事
    所以,我同意 Sakata 的观点,你不应该找到解决方法。

    【讨论】:

    • 谢谢。我没有在我的示例类中使用任何模块,所以我有点不清楚你的意思。同样从您的回答看来, First 一旦使用它就会保留对 Second 的引用。这种魔法是如何发生的?
    • 谢谢。我没有在我的示例类中使用任何模块,所以我有点不清楚你的意思。对不起,我在解释中的意思是“第一”类。顺便说一下,Class 的超类是 Module。
    • 另外,从您的回答看来,First 一旦使用它就会保留对 Second 的引用。这种魔法是如何发生的? 我不知道你所说的“First 保持对 Second 的引用”是什么意思,我的意思是当你调用 x.foo 时,ruby 执行代码并遇到一个未知的常量名称“Second”并且调用“const_missing”,这就是 Rails 的用武之地,它会覆盖此方法以自动加载丢失的常量。您可以参考“urbanautomaton.com/blog/2013/08/27/rails-autoloading-hell”了解有关在 rails 中自动加载的更多信息。
    • 非常感谢,我现在开始明白了。这种复杂而低级的铁轨。我希望参考资料能帮助我了解更多
    【解决方案2】:

    看来重新加载控制台环境并尝试引用之前创建的实例并不是一件好事。所以我认为你不应该找到解决方法。

    【讨论】:

    • 谢谢,如果没有其他答案,我会稍等一下,然后再接受
    猜你喜欢
    • 1970-01-01
    • 2012-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-15
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多