【问题标题】:LoadError occurs apparently at randomLoadError 显然是随机发生的
【发布时间】:2014-05-27 14:24:47
【问题描述】:

有时我会收到此错误:

LoadError:预期 /app/lib/services/foo/errors/login_failed.rb 定义 Errors::LoginFailed

文件/lib/services/dvr_providers/website/bar.rb中出现错误:

module Services
  module Foo
    module Website
      class Bar < Base

        def some_method
          raise Errors::LoginFailed.new(some_param) if cannot_log_in

文件/lib/services/foo/errors/login_failed.rb 包含:

module Services
  module Foo
    module Errors
      class LoginFailed < StandardError

我无法在开发中复制这一点。我还验证了代码在生产中通常可以正常运行。

请注意,Rails 正在尝试解析为 /app/lib。我应该提到我在app\models 下的两个不同子文件夹中还有两个名为login_failed.rb 的文件。

有什么建议吗?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3.1


    【解决方案1】:

    这通常是由于自动加载器在循环运行时尝试加载具有依赖关系的类而导致的。根据自动加载链开始的位置,这有时会失败。考虑这个例子:

    # base.rb
    class Base
      self.set_thing(opts)
        # do it
      end
    
      set_thing MyStuff::BAZ
    end
    
    # foo.rb
    class Foo < Base
      STUFF = "things"
    
      set_thing MyStuff::FOOBAR
    end
    
    # my_stuff.rb
    module MyStuff
      FOOBAR = "foobar"
      BAZ = "baz"
    
      def self.doit(something)
        # DO IT
      end
    
      doit Foo::STUFF
    end
    

    这里你有一个常量之间的循环依赖。在加载类时,Rails 会尝试自动加载相应的源文件来解析常量。

    如果您首先加载Base,那么一切都应该正常。它应该开始创建Base 类,然后是MyStuff,然后是Foo

    但是,如果您从Foo 开始,它需要Base,而MyStuff 本身需要Foo 中尚未加载的内容。因此,Autoloader 无法完全解析加载队列并中止。

    为了缓解这个问题,您可以尝试通过将常量查找移到稍后阶段来打破依赖循环,例如通过使用块或方法进行惰性求值,而不是直接在类中声明。

    【讨论】:

    • 谢谢;这很有启发性,但我认为这不是我的问题。 LoginFailed 类除了在初始化程序中调用 super 并传入由字符串参数组成的字符串外,什么都不做。
    猜你喜欢
    • 2017-09-28
    • 2019-03-25
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    相关资源
    最近更新 更多