สำเนาของ xxx ถูกลบออกจากโครงสร้างโมดูล แต่ยังทำงานอยู่


130

ฉันค่อนข้างมั่นใจว่าข้อผิดพลาดไม่เกี่ยวข้องกับเนื้อหาจริงของ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 / บริษัท / 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 ออกคุณยังคงได้รับข้อผิดพลาดหรือไม่?
Frederick Cheung

@WaynnLue ใช่ฉันคิดว่านั่นเป็นเหตุผลฉันไม่รู้ว่าจะแก้ไขอย่างไร
kddeisz

@FrederickCheung ฉันมีไฟล์อื่นที่คล้ายกับไฟล์นี้ซึ่งมีข้อผิดพลาดในลักษณะเดียวกันและมักมีข้อผิดพลาดในบรรทัดที่เกี่ยวข้องกับผู้เช่าดังนั้นจึงเป็นการเดาที่ดีที่สุดของฉัน
kddeisz

1
แม้ว่าคุณจะไม่ได้ใช้ Wisper ใน Rails ที่นี่ แต่อาจเป็นประโยชน์สำหรับคนอื่นที่จะทราบว่า Wisper ทำให้เกิดปัญหานี้อย่างสม่ำเสมอหากคุณไม่ปฏิบัติตามคำแนะนำในชุดข้อความนี้: stackoverflow.com/questions/28346609/…
Steve N

คำตอบ:


183

Tenant เป็นปลาชนิดหนึ่งสีแดง - ข้อผิดพลาดจะเกิดขึ้นหากคุณอ้างถึงแอปใด ๆ ที่ต้องโหลดโดยราง ' const_missingเคล็ดลับ

ปัญหาคือคุณกำลังนำสิ่งที่โหลดซ้ำได้ (โมดูลของคุณ) แล้วรวมไว้ในสิ่งที่ไม่สามารถโหลดซ้ำได้ ( ActiveRecord::Baseหรือในตัวอย่างก่อนหน้านี้ของคุณActionMailer::Base) เมื่อถึงจุดหนึ่งโค้ดของคุณจะถูกโหลดซ้ำและตอนนี้ ActiveRecord ยังคงมีโมดูลนี้รวมอยู่แม้ว่ารางจะคิดว่ามันได้ยกเลิกการโหลดแล้วก็ตาม ข้อผิดพลาดเกิดขึ้นเมื่อคุณอ้างอิงผู้เช่าเนื่องจากทำให้รางเรียกใช้const_missingตะขอเพื่อค้นหาว่าผู้เช่าควรโหลดจากที่ใดและรหัสนั้นจะหลุดออกเนื่องจากโมดูลที่การค้นหาคงที่เริ่มต้นจากไม่ควรอยู่ที่นั่น

มี 3 วิธีแก้ไขที่เป็นไปได้:

  1. หยุดรวมโมดูลของคุณไว้ในคลาสที่ไม่สามารถโหลดซ้ำได้ - รวมไว้ในโมเดลแต่ละตัวคอนโทรลเลอร์ตามต้องการหรือสร้างคลาสพื้นฐานที่เป็นนามธรรมและรวมโมดูลไว้ในนั้น

  2. ทำให้โมดูลนี้ไม่สามารถโหลดซ้ำได้โดยจัดเก็บไว้ในที่อื่นที่ไม่ได้อยู่ใน autoload_paths (คุณจะต้องกำหนดให้ใช้อย่างชัดเจนเนื่องจากรางจะไม่โหลดอย่างน่าอัศจรรย์สำหรับคุณอีกต่อไป)

  3. การเปลี่ยนผู้เช่าเป็น :: ผู้เช่า ( Object.const_missingจะถูกเรียกใช้ไม่ใช่Tenant.const_missing)


30
ดูเหมือนว่าฉันจะพบวิธีที่สามแล้ว แต่ฉันก็สงสัยว่าคุณรู้ไหมว่าทำไมมันถึงได้ผล ถ้าฉันอ้างอิงว่า :: ผู้เช่าทุกอย่างทำงานได้อย่างน่าอัศจรรย์ อาจเป็นเพราะมันโหลดเป็นค่าคงที่ระดับบนสุด? อาจจะ?
kddeisz

3
จากนั้นเป็น Object.const_missing ที่จะถูกเรียกไม่ใช่ YourModule.const_missing ดังนั้นสิ่งต่างๆควรได้ผล
Frederick Cheung

6
การสำรองข้อมูลไปยังระดับบนสุดโดยใช้::ก็ใช้ได้ผลเช่นกัน!
Alex Moore-Niemi

7
ฉันมีปัญหานี้เกิดขึ้นเป็นครั้งคราวและในกรณีของฉันมันเกี่ยวข้องกับฤดูใบไม้ผลิดังนั้นการ./bin/spring stopแก้ไขก็คือการแก้ไข
santuxus

2
ฉันชอบที่นี่เป็นข้อผิดพลาดของรันไทม์ Ruby / Rails ซึ่งแตกต่างจากภาษาอื่น ๆ ไม่ว่าจะเป็นแบบไดนามิกหรือไม่ Ruby ช่วยให้นักพัฒนามีความยืดหยุ่นที่ไม่ จำกัด อย่างแท้จริงโดยไม่รู้ว่าโมดูลจะถูกกำหนดไว้ที่ใดจนกว่าโปรแกรมของคุณจะดำเนินการ (และจะดำเนินการในลำดับใด) ออกแบบมาอย่างดี
Andy Ray


6

ไม่แน่ใจว่าสิ่งนี้จะช่วยใครได้หรือไม่ แต่ฉันมีสิ่งนี้เกิดขึ้นกะทันหันหลังจากการเปลี่ยนแปลงที่ดูเหมือนไม่เกี่ยวข้องกัน มันหายไปหลังจากที่ฉันรีสตาร์ทแอ็พพลิเคชันเซิร์ฟเวอร์



0

อะไรที่เหมาะกับฉัน:

ปรับปรุง config.eager_load = falseเป็นtrue

ใน config/environments/development.rb

รูบี้ 2.6.5
ราง 5.1.6


1
ใช่ไม่ทำอย่างนี้แน่นอน นั่นจะเป็นการฆ่าความสามารถของคุณในการโหลดโค้ดซ้ำในการพัฒนา
kddeisz

-14

บางครั้งคุณก็เฉยๆ

รีสตาร์ทเซิร์ฟเวอร์ของคุณ


ฉันไม่เข้าใจว่าทำไมจึงลงคะแนนคำตอบนี้? ซ้ำแปลว่าสำคัญ! ทำไมเรื่องง่ายๆจึงมีเรื่องไร้สาระมากมาย
อัลเบิร์ต

7
สิ่งนี้ถูกลดลงเนื่องจาก (a) ไม่ว่าคุณจะรีสตาร์ทเซิร์ฟเวอร์กี่ครั้งก็จะไม่สามารถแก้ปัญหาในคำถามเดิมได้และ (b) คุณไม่ควรเพียงแค่รักษาอาการของปัญหา แต่เป็นปัญหาเอง
tjbp

@tjbp โปรดระวังคำว่า "บางครั้ง" ok?
อัลเบิร์ต

ปัญหาคือเป็นไปไม่ได้ที่จะดีบักแอปพลิเคชันในโหมดการพัฒนาหากคุณต้องรีสตาร์ทเซิร์ฟเวอร์ทุกครั้งหลังการเปลี่ยนแปลง
Max Ivak

2
ฉันจะลงคะแนนให้สำหรับคำตอบนี้เพราะถ้าคุณใช้ mongoid และลบ object X ออกจากรางคอนโซลคุณจะได้รับข้อผิดพลาดนี้: A copy of X has been removed from the module tree but is still activeในทุกหน้าที่มี Object Y.embeds Xและการรีสตาร์ทเซิร์ฟเวอร์ใช้งานได้จริงสำหรับกรณีนี้ แต่คุณควรแก้ไขคำตอบของคุณ
Lucas Andrade
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.