web-dev-qa-db-ja.com

xxxのコピーがモジュールツリーから削除されましたが、まだアクティブです

エラーはTenantIdLoaderモジュールの実際の内容とは何の関係もないと確信しています。代わりに、ActiveSupport依存関係と関係があります。

私はこのエラーを乗り越えることができないようです。私が読んだことから、それはActiveRecord::Baseがリロードされるか、Company::TenantIdLoaderがリロードされるためであり、どういうわけかそれは通信していません。助けてください! Rails 4.2にアップグレードできるようになりたいです。

編集

自動的にリロードされる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
115
kddeisz

Tenantは一種の赤いニシンです-Railsのconst_missingトリックによってロードする必要があるアプリのビットを参照した場合、エラーが発生します。

問題は、リロード可能なもの(モジュール)を取得し、それをリロードできないもの(ActiveRecord::Baseまたは以前の例ではActionMailer::Base)に含めることです。ある時点でコードがリロードされ、Railsがアンロードしたと考えていても、ActiveRecordにはこのモジュールが含まれています。テナントを参照すると、エラーが発生します。これにより、Railsがconst_missingフックを実行して、テナントのロード元を見つけ、定数検索が開始されるモジュールが原因でコードがフリークするためです。そこにいるべきではありません。

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

  1. モジュールを再読み込み不可能なクラスに含めるのをやめます-必要に応じて個々のモデル、コントローラーに含めるか、抽象基本クラスを作成してそこにモジュールを含めます。

  2. Autoload_pathsにない場所に保存して、このモジュールを再ロード不可にします(Railsが魔法のようにロードしなくなるため、明示的に要求する必要があります)

  3. テナントを:: Tenantに変更します(Object.const_missingではなく、Tenant.const_missingが呼び出されます)

159

ModuleName:: ModuleNameに変更するとうまくいきました。

26
Aman Kumar

これがだれにも役立つかどうかはわかりませんが、関係のないように見える変更の後に突然発生し始めました。アプリケーションサーバーを再起動すると消えました。

4
beef_boolean