Копію xxx видалено з дерева модулів, але вона все ще активна


129

Я впевнений, що помилка не має нічого спільного з фактичним вмістом TenantIdLoaderмодуля. Натомість це має щось спільне із ActiveSupportзалежностями.

Я, здається, не можу пройти цю помилку З того, що я прочитав, це тому, що або ActiveRecord::Baseвін перезавантажується, або Company::TenantIdLoaderперезавантажується, і це якось не повідомляє про це. Допоможіть, будь ласка! Я дуже хотів би мати можливість перейти на Rails 4.2.

EDIT

Зараз я дізнався, що це тому, що я Tenantпосилаюсь, що автоматично завантажується. Мені потрібно вміти фактично посилатися на клас, тож хтось знає, як це обійти?

config / application.rb

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

config / ініціалізатори / 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

3
Чи допомагає ця відповідь взагалі? stackoverflow.com/questions/17561697 / ...
Waynn LUE

Ви впевнені, що клас Орендаря бере участь? Якщо ви заглушите біти цього коду, який використовує Tenant, ви все-таки отримаєте помилку?
Фредерік Чеунг

@WaynnLue так, я думаю, це причина, я просто не знаю, як це виправити.
kddeisz

@FrederickCheung У мене є ще один файл, схожий на цей, який помиляється аналогічно, і він завжди помиляється у рядку, пов'язаному з Орендарем, тому я найкраще здогадався.
kddeisz

1
Хоча тут Ви не використовуєте Wisper в Rails, іншим може бути корисно відзначити, що Wisper викликає цю проблему досить послідовно, якщо ви не дотримуєтесь порад у цій темі: stackoverflow.com/questions/28346609/…
Стів N

Відповіді:


182

Tenantє своєрідною червоною оселедець - помилка може статися, якщо ви посилаєтесь на будь-який біт програми, яку потрібно завантажити трек const_missingрейків.

Проблема полягає в тому, що ви берете щось завантажуване (ваш модуль), а потім включаєте його в щось, що не завантажується ( ActiveRecord::Baseабо, у попередньому прикладі ActionMailer::Base). В якийсь момент ваш код перезавантажується, і тепер ActiveRecord все ще містить цей модуль в ньому, хоча рейли вважають, що він його вивантажив. Помилка виникає, коли ви посилаєтеся на Tenant, оскільки це призводить до того, що рейки запускають його const_missingгачки, щоб з’ясувати, звідки слід завантажувати Tenant, і цей код вироджується, оскільки модуля, з якого починається постійний пошук, не повинно бути там.

Є 3 можливі рішення:

  1. Перестаньте включати модуль у класи, що не завантажуються - або включайте в окремі моделі, контролери за потребою, або створюйте абстрактний базовий клас і включайте модуль туди.

  2. Зробіть цей модуль не завантажуваним, зберігаючи його там, де немає в autoload_paths (вам доведеться вимагати цього явно, оскільки рейки більше не завантажуватимуть вас магічно)

  3. Зміна орендодавця на :: орендар ( Object.const_missingтоді буде викликано, не Tenant.const_missing)


30
Я, здається, знайшов третє рішення, хоча мені було цікаво, чи знаєте ви, чому це працює. Якщо я посилаюсь на це: Орендар, все виходить магічно. Можливо, тому що він завантажує його як константу верхнього рівня? Може бути?
kddeisz

3
то виклик буде Object.const_missing, а не YourModule.const_missing, тому все повинно вийти
Фредерік Чеунг

6
Резервне копіювання на найвищому рівні використовувалось і ::для мене!
Алекс Мур-Ніємі

7
У мене це питання час від часу виникало, і в моєму випадку воно було пов'язане з весною, тому це ./bin/spring stopвирішувалося.
santuxus

2
Я люблю, що це помилка Ruby / Rails під час виконання - на відміну від будь-якої іншої мови, динамічної чи ні, Ruby надає розробникам справжню необмежену гнучкість, щоб вони буквально не мали уявлення, де визначаються модулі, поки ваша програма не виконує (і в якому порядку вона виконує). Це так добре розроблено.
Енді Рей


6

Не впевнений, чи допоможе це комусь, але мені це раптом почалося відбуватися після зміни, яка здавалася не пов'язаною. Він пішов після того, як я перезапустив сервер додатків.


0

Змінюючись, ModuleNameщоб 'ModuleName'.constantizeвирішити питання для мене.


0

Що для мене спрацювало:

Оновити config.eager_load = falseдоtrue

в config/environments/development.rb

Рубіни 2.6.5
Рейки 5.1.6


1
Так, точно не роби цього. Це знищить вашу здатність перезавантажувати код у розробці.
kddeisz

-13

Іноді ти просто

Перезавантажте сервер,


Я не розумію, чому спростовую цю відповідь? Повторити означає, що це важливо! Чому прості речі мають багато дурниць?
Альберт.цин

7
Це недоцільно, оскільки (а) незалежно від того, скільки разів ви перезавантажуєте сервер, це не вирішить проблему в первісному питанні, і (б) ви повинні не просто лікувати симптоми проблеми, а саму проблему.
tjbp

@tjbp plz уважно ставиться до слова "інколи" гаразд?
Альберт.цин

проблема полягає в тому, що неможливо налагодити додаток у режимі розробки, якщо вам доведеться перезапускати сервер після кожної зміни.
Макс Івак

2
Я проголосую за цю відповідь, тому що якщо ви використовуєте монгоїд і видаляєте об’єкт X з консолі рейлів, ви отримаєте цю помилку: A copy of X has been removed from the module tree but is still activeна всіх сторінках, які мають Object Y.embeds X, і сервер перезавантаження дійсно працює для цього конкретного випадку. Але вам слід відредагувати свою відповідь.
Лукас Андраде
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.