Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 子类的循环依赖关系_Ruby On Rails_Ruby_Circular Dependency_Activesupport - Fatal编程技术网

Ruby on rails 子类的循环依赖关系

Ruby on rails 子类的循环依赖关系,ruby-on-rails,ruby,circular-dependency,activesupport,Ruby On Rails,Ruby,Circular Dependency,Activesupport,假设我们使用的是Rails或者仅仅是ActiveSupport::Dependenciesmodule。现在让我们看看这段代码: animal.rb class Animal CHILD = { cat: Cat } # factory!? def self.child(name) CHILD[name].new end end cat.rb class Cat < Animal end 该代码将导致aB不是类(TypeError)(actives

假设我们使用的是Rails或者仅仅是
ActiveSupport::Dependencies
module。现在让我们看看这段代码:

animal.rb

class Animal
  CHILD = {
    cat: Cat
  }

  # factory!?
  def self.child(name)
    CHILD[name].new
  end
end
cat.rb

class Cat < Animal
end
该代码将导致a
B不是类(TypeError)
(activesupport 3.x)或自动加载常量B(activesupport 4.x)时检测到的
循环依赖项,因为它尚未创建,但类的名称已在类表中

要解决此问题,可以
要求“a”
,然后
a
将要求
B


能否为以下问题提供更好的解决方案?

因此,为了避免在Rails初始化或加载特定类时自动加载大量其他类,Rails使用字符串指定关联的类名(如果需要指定),例如

has_many :published_posts, class_name: 'Post'
因为联想最容易产生这样的互动

因此,如果您可以控制自己使用的内容,并且可以通过使用字符串保存常量的名称直到需要对其进行常量化,从而延迟常量的加载,直到Ruby/Rails中需要它,那么这可能不是一个坏主意。但是,像任何事情一样,最佳解决方案取决于您的需求


如果您来自另一种编程语言背景(如Java),至少在历史上,由于开销(至少在旧版本中)的原因,开发人员会避免使用反射从字符串动态实例化类,那么这似乎很奇怪以及稍后加载类时出错的可能性,而不是在启动时尽早捕获它们。但是,这真的不是一件坏事。而且这也不会阻止您提前急切地加载,因为它实际上是在消除加载过程中由常量引用引起的直接依赖性。

因此,为了避免在Rails初始化或加载特定类时自动加载大量其他类,如果需要指定,Rails使用字符串指定关联的类名,例如

has_many :published_posts, class_name: 'Post'
因为联想最容易产生这样的互动

因此,如果您可以控制自己使用的内容,并且可以通过使用字符串保存常量的名称直到需要对其进行常量化,从而延迟常量的加载,直到Ruby/Rails中需要它,那么这可能不是一个坏主意。但是,像任何事情一样,最佳解决方案取决于您的需求


如果您来自另一种编程语言背景(如Java),至少在历史上,由于开销(至少在旧版本中)的原因,开发人员会避免使用反射从字符串动态实例化类,那么这似乎很奇怪以及稍后加载类时出错的可能性,而不是在启动时尽早捕获它们。但是,这真的不是一件坏事。而且,这也不会阻止您提前急切地加载,因为它实际上是在消除加载过程中由常量引用引起的直接依赖。

如果您不想/不能使用
require
,则应避免循环依赖。避免它们的一种方法是用运行时级调用替换类加载级调用:

class Animal
  CHILD = {
    cat: 'Cat'
  }

  def self.child(name)
    CHILD[name].constantize.new
  end
end

实际上,
self.child
现在不能在类级别调用,否则您将再次处于循环依赖上下文中。

如果您不想/不能使用
require
,则应避免循环依赖。避免它们的一种方法是用运行时级调用替换类加载级调用:

class Animal
  CHILD = {
    cat: 'Cat'
  }

  def self.child(name)
    CHILD[name].constantize.new
  end
end

实际上,
self.child
现在不能在类级别调用,否则您将再次处于循环依赖上下文中。

您能更好地了解您打算做什么吗?一般来说,我想不出为什么一个类需要知道它自己的子类。循环引用很麻烦,除非你有一个特定的用例需要它。通常,这个问题可以通过其他方式解决-循环依赖需要什么?@dsatch,我正在设置父类中的子类的映射哈希常量。作为一个解决方案,我可以将常数移动到使用它的方法,但我认为这不是一个合适的方法。我只是意识到这只是一个工厂模式。但是无论如何,我想上面的解决方案是最好的解决方案:CONST在类级别(它可以重用),而
child
方法是一个工厂方法,用于构造正确的类。你能更好地了解你打算做什么吗?一般来说,我想不出为什么一个类需要知道它自己的子类。循环引用很麻烦,除非你有一个特定的用例需要它。通常,这个问题可以通过其他方式解决-循环依赖需要什么?@dsatch,我正在设置父类中的子类的映射哈希常量。作为一个解决方案,我可以将常数移动到使用它的方法,但我认为这不是一个合适的方法。我只是意识到这只是一个工厂模式。但无论如何,我想上面的解决方案是最好的解决方案:CONST在类级别(可以重用),而
child
方法是一个工厂方法,用于构造正确的类。很好,但在我的示例中,我使用的是ActiveAdmin,即在通过路由初始化模型之后立即初始化模型。我已经将我的示例更新为更现实的用例。谢谢!是的,因为你改变了问题,我的答案看起来不正确,但会保持原样。基本上,这个想法是为了避免循环依赖,可以将常量存储为字符串,并在类加载后的某个时间进行常量化。你甚至可能想在常量化之后缓存/存储常量,如果它能提高效率的话。很好,但在我的示例中,我使用的是ActiveAdmin,即在通过路由初始化之后立即初始化模型。我已经将我的示例更新为更现实的用例。谢谢!是的,自从