微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Ruby/Rails:在 ApplicationRecord 中包含关注点时的循环依赖

如何解决Ruby/Rails:在 ApplicationRecord 中包含关注点时的循环依赖

我担心创建一个类宏,我希望该宏可用于 Rails 应用程序中的所有模型。所以我将它包含在 ApplicationRecord 中。代码如下:

# application_record.rb

class ApplicationRecord < ActiveRecord::Base

  include ::TestConcern

end

# app/concerns/test_concern.rb

module TestConcern

  extend ActiveSupport::Concern

  class_methods do

    def some_class_macro_all_models_must_have

      User.some_class_instance_variable << self

    end

  end

  included do
    User.include(UserModule)
  end

  module UserModule

    def self.included(base)
      base.class_eval do

        def self.some_class_instance_variable
          @some_class_instance_variable ||= Set.new
        end

      end
    end

  end

end

如您所见,类宏实际上会与模型 User 中的类实例变量进行交互。

这就是为什么,在关注的包含钩子上,我试图class_eval User 模型来初始化该类实例变量。计划是这样做的,否则任何模型都可以在用户模型中初始化类实例变量之前调用类宏。

然而,这会以 Circular dependency detected while autoloading constant User 出错。据我所知,ApplicationRecord 加载,它包含模块,模块 included 钩子被调用,它引用了 User 模型,因此加载了 User 模型,它继承了来自ApplicationRecord(尚未完成加载),因此会导致循环依赖。

如何避免这种循环依赖悖论,知道很多模型调用这个类宏,而且那些类可能会在 User 类本身之前加载,所以我什至不能指望定义 some_class_instance_variable方法用户模型本身?

解决方法

经过深思熟虑后,我决定简单地将 some_class_instance_variable 存储在关注点本身中,并且由于模型 User 也称为 some_class_macro_all_models_must_have,因此我决定包含 UserModule当它被调用时,有效地消除了循环依赖加载顺序问题。

真正的代码比这个人为的例子复杂得多,但最终的结果是这样的:

module TestConcern

  def self.some_class_instance_variable
    @some_class_instance_variable ||= Set.new
  end

  extend ActiveSupport::Concern

  class_methods do

    def some_class_macro_all_models_must_have

      User.include(UserModule) if self == User

      TestConcern.some_class_instance_variable << self

    end

  end

  included do
  end

  module UserModule

    def self.included(base)
      base.class_eval do

        # Class macro invocations,class method and instance method definitions

      end
    end

  end

end

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?