エラーは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
Tenant
は一種の赤いニシンです-Railsのconst_missing
トリックによってロードする必要があるアプリのビットを参照した場合、エラーが発生します。
問題は、リロード可能なもの(モジュール)を取得し、それをリロードできないもの(ActiveRecord::Base
または以前の例ではActionMailer::Base
)に含めることです。ある時点でコードがリロードされ、Railsがアンロードしたと考えていても、ActiveRecordにはこのモジュールが含まれています。テナントを参照すると、エラーが発生します。これにより、Railsがconst_missing
フックを実行して、テナントのロード元を見つけ、定数検索が開始されるモジュールが原因でコードがフリークするためです。そこにいるべきではありません。
3つの解決策があります。
モジュールを再読み込み不可能なクラスに含めるのをやめます-必要に応じて個々のモデル、コントローラーに含めるか、抽象基本クラスを作成してそこにモジュールを含めます。
Autoload_pathsにない場所に保存して、このモジュールを再ロード不可にします(Railsが魔法のようにロードしなくなるため、明示的に要求する必要があります)
テナントを:: Tenantに変更します(Object.const_missing
ではなく、Tenant.const_missing
が呼び出されます)
ModuleNameを:: ModuleNameに変更するとうまくいきました。
これがだれにも役立つかどうかはわかりませんが、関係のないように見える変更の後に突然発生し始めました。アプリケーションサーバーを再起動すると消えました。