1. ホーム
  2. ruby-on-rails

[解決済み] xxxのコピーはモジュールツリーから削除されましたが、まだアクティブです。

2022-05-10 20:18:12

質問

の実際の内容とは関係ないことは確かです。 TenantIdLoader モジュールの実際のコンテンツとは関係がないことは確かです。代わりに、それは ActiveSupport 依存関係があります。

私はこのエラーを乗り越えることができないようです。私が読んだところでは、それはどちらかが ActiveRecord::Base が再読み込みされているか Company::TenantIdLoader が再読み込みされているのに、なぜかそれが伝わらないのです。助けてください!お願いします Rails 4.2にアップグレードされることを強く望んでいます。

EDIT

を参照しているからだと今更ながら知りました。 Tenant を参照しているからだということがわかりました。しかし、私は実際にクラスを参照できるようにする必要があるので、誰かこれを回避する方法を知っていますか?

config/application.rb

config.autoload_paths += %W( #{config.root}/lib/company )

config/initializers/company.rb

ActionMailer::Base.send(:include, Company::TenantIdLoader)

lib/company/tenant_id_loader.rb

module Company
  module TenantIdLoader

    extend ActiveSupport::Concern

    included do
      cattr_accessor :tenant_dependency
      self.tenant_dependency = {}
  
      after_initialize do
        self.tenant_id = Tenant.active.id if self.class.tenant_dependent? and self.new_record? and Tenant.active.present? and !Tenant.active.zero?
      end
    end

    # class methods to be mixed in
    module ClassMethods
  
      # returns true if this model's table has a tenant_id
      def tenant_dependent?
        self.tenant_dependency[self.table_name] ||= self.column_names.include?('tenant_id')
      end
  
    end

  end
end

どのように解決するのですか?

Tenant は赤信号のようなもので、rails'で読み込む必要のあるアプリのビットを参照した場合にエラーが発生します。 const_missing トリックによってロードされる必要があるアプリを参照するとエラーが発生します。

問題は、リロード可能なもの (あなたのモジュール) を、リロード不可能なもの ( ActiveRecord::Base または、先ほどの例で言えば ActionMailer::Base ). ある時点でコードがリロードされると、railsがアンロードしたと思っていても、ActiveRecordにはまだこのモジュールが含まれています。Tenantを参照したときにエラーが発生するのは、railsがその const_missing フックを実行し、Tenantがどこからロードされるべきかを検索するため、定数検索が開始されるモジュールが存在しないはずなので、そのコードはパニックになります。

3つの可能な解決策があります。

  1. 必要に応じて個々のモデルやコントローラに含めるか、抽象的な基底クラスを作成し、そこにモジュールを含めるかです。

  2. このモジュールを autoload_paths 以外の場所に保存して、リロードできないようにします (rails が魔法のようにロードしなくなるので、明示的に要求する必要があります)。

  3. Tenantを::Tenantに変更する ( Object.const_missing が呼び出されます。 Tenant.const_missing )