【问题标题】:Dynamic concerns with inheritance not loading twice, but only once继承的动态问题不加载两次,但只加载一次
【发布时间】:2022-10-24 07:35:22
【问题描述】:

我们正在基于一些环境变量动态加载代码,效果非常好。

像这样的东西:

# User class
class User
  include DynamicConcern
end
module DynamicConcern
  extend ActiveSupport::Concern

  included do
    if "Custom::#{ENV["CUSTOMER_NAME"].camelize}::#{self.name}Concern".safe_constantize
      include "Custom::#{ENV["CUSTOMER_NAME"].camelize}::#{self.name}Concern".constantize 
    end
  end
end
# custom code
module Custom::Custom123::UserConcern
  extend ActiveSupport::Concern
  
  included do
    ...
  end
end

多年来我们一直在使用它,它在模型中运行得非常好。几天前,我们尝试对控制器使用相同的方法,但意识到这种方法并没有 t 可以很好地处理继承,其中父类继承了关注点以及继承的类:

class ApplicationController < ActionController::Base
  # this gets loaded and includes the right dynamic module
  include DynamicConcern 
end

class ShopController < ApplicationController
  # this is NOT getting loaded again and skipped, 
  # since it has been loaded already in the parent controller
  include DynamicConcern 
end

有没有办法告诉rails它应该第二次包含/评估关注点,因为第二次它会有另一个包含另一个模块的类名?

我不是在寻找其他解决方案,因为我们的很多代码都是基于这种方法的,我认为可以在不重写所有内容的情况下解决这个问题。

谢谢!

【问题讨论】:

    标签: ruby-on-rails ruby inheritance separation-of-concerns activesupport-concern


    【解决方案1】:

    您只是尝试根据类名动态包含模块。

    不需要关注,但它可以是一个普通的类,并且包含操作可以是一个普通的方法。每次你想调用它时,只要像其他任何方法一样调用它。

    因为您已经以include 的方式使用ActiveSupport::Concern 编写了代码。我想即使我不能保证以下重构可能会起作用。这个想法很简单:

    1. 只要把目标类做为参数的普通方法即可。您可以包含它(它会自动在included 挂钩中调用dynamic_include)。
    2. 如果模块已经包含在祖先层次结构链中,只需调用dynamic_include 将立即调用该方法并进行动态包含。

      请试一试,让我知道它是否适用于您的场景。

      module DynamicConcern
        extend ActiveSupport::Concern
      
        included do
          def self.dynamic_include(klass)
            if "Custom::#{ENV["CUSTOMER_NAME"].camelize}::#{klass.name}Concern".safe_constantize
              klass.include "Custom::#{ENV["CUSTOMER_NAME"].camelize}::#{klass.name}Concern".constantize 
            end
          end
          dynamic_include(self)
        end
      end
      
      class ApplicationController < ActionController::Base
        # this gets loaded and includes the right dynamic module
        include DynamicConcern 
      end
      
      class ShopController < ApplicationController
        # this is NOT getting loaded again and skipped, 
        # since it has been loaded already in the parent controller
        dynamic_include(self)
      end
      

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 2011-09-15
      • 2016-10-02
      • 1970-01-01
      • 1970-01-01
      • 2022-08-23
      • 1970-01-01
      • 2016-06-14
      • 2021-07-07
      相关资源
      最近更新 更多