ActiveRecord, has_many: through และ Polymorphic Association


117

folks,

ต้องการให้แน่ใจว่าฉันเข้าใจสิ่งนี้ถูกต้อง และโปรดเพิกเฉยต่อกรณีการสืบทอดที่นี่ (SentientBeing) โดยพยายามมุ่งเน้นไปที่โมเดลหลายรูปแบบใน has_many: ผ่านความสัมพันธ์ ที่กล่าวมาให้พิจารณาดังต่อไปนี้ ...

class Widget < ActiveRecord::Base
  has_many :widget_groupings

  has_many :people, :through => :widget_groupings, :source => :person, :conditions => "widget_groupings.grouper_type = 'Person'"
  has_many :aliens, :through => :widget_groupings, :source => :alien, :conditions => "video_groupings.grouper_type = 'Alien'"
end

class Person < ActiveRecord::Base
  has_many :widget_groupings, :as => grouper
  has_many :widgets, :through => :widget_groupings
end

class Alien < ActiveRecord::Base
  has_many :widget_groupings, :as => grouper
  has_many :widgets, :through => :widget_groupings  
end

class WidgetGrouping < ActiveRecord::Base
  belongs_to :widget
  belongs_to :grouper, :polymorphic => true
end

ในโลกที่สมบูรณ์แบบฉันต้องการให้วิดเจ็ตและบุคคลทำสิ่งที่ชอบ:

widget.people << my_person

อย่างไรก็ตามเมื่อฉันทำเช่นนี้ฉันสังเกตเห็นว่า 'type' ของ 'grouper' นั้นเป็นโมฆะเสมอใน widget_groupings อย่างไรก็ตามหากฉันทำสิ่งต่อไปนี้:

widget.widget_groupings << WidgetGrouping.new({:widget => self, :person => my_person}) 

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

ขอบคุณสำหรับความช่วยเหลือ!

คำตอบ:


162

มีปัญหาที่ทราบเกี่ยวกับ Rails 3.1.1 ที่ทำให้ฟังก์ชันนี้หยุดทำงาน หากคุณประสบปัญหานี้ก่อนลองอัปเกรดปัญหาได้รับการแก้ไขแล้วใน 3.1.2

คุณใกล้มากแล้ว ปัญหาคือคุณใช้ตัวเลือก: source ในทางที่ผิด : แหล่งที่มาควรชี้ไปที่ความสัมพันธ์แบบ polymorphic belong_to จากนั้นสิ่งที่คุณต้องทำคือระบุ: source_type สำหรับความสัมพันธ์ที่คุณพยายามกำหนด

การแก้ไขโมเดลวิดเจ็ตนี้จะช่วยให้คุณทำสิ่งที่ต้องการได้อย่างแท้จริง

class Widget < ActiveRecord::Base
  has_many :widget_groupings

  has_many :people, :through => :widget_groupings, :source => :grouper, :source_type => 'Person'
  has_many :aliens, :through => :widget_groupings, :source => :grouper, :source_type => 'Alien'
end

โอ้พระเจ้าของฉันที่เห็นได้ชัดอย่างเจ็บปวดฉันไม่อยากจะเชื่อเลยว่าฉันเคลือบมันลงไป ขอบคุณ EmFi!
Cory

ไม่มีปัญหาฉันคิดว่าฉันทรมานมาประมาณหนึ่งวันแล้วว่าจะทำอย่างไรในครั้งแรกที่ฉันเจอ ไม่ได้ช่วยเลยว่านี่เป็นสิ่งแรก ๆ ที่ฉันพยายามทำใน Rails ที่ไม่เกี่ยวข้องกับการทำตามบทช่วยสอน / หนังสือ
EmFi

1
ดังที่ scotkf ชี้ให้เห็นว่ามีการถดถอยใน ActiveRecord 3.1.1 ที่บล็อกพฤติกรรมนี้ การอัปเกรดเป็น 3.1.2 จะทำให้โซลูชันนี้ใช้งานได้
EmFi

6
เช่นเดียวกับสิ่งที่ @Shtirlic กล่าวถึง มีวิธีไม่ระบุ source_type คุณจึงมีชุดผลลัพธ์แบบผสมหรือไม่? หากใครแก้ไขปัญหานี้ได้ชอบที่จะรู้วิธี
Damon Aw

3
ยังคงใช้งานได้เหมือน Rails 4.2.0 อย่างไรก็ตามมีวิธีใดบ้างที่จะทำสิ่งนี้ให้สำเร็จในทุกวันนี้โดยไม่มี source_type และการเชื่อมโยงสองแบบแยกกัน
Emeka

3

ดังที่ได้กล่าวมาแล้วสิ่งนี้ใช้ไม่ได้กับราง 3.1.1 เนื่องจากมีข้อบกพร่องใน: source แต่ได้รับการแก้ไขแล้วใน Rails 3.1.2


-4

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

ฉันไม่คิดว่ามันเป็นข้อบกพร่องมันเป็นเพียงสิ่งที่ยังไม่ได้นำไปใช้ ฉันคิดว่าเราจะเห็นมันในคุณสมบัตินี้เพราะทุกคนมีกรณีที่พวกเขาสามารถใช้มันได้


6
พวกเขาทำงานร่วมกัน ตัวอย่างเช่น has_many: Subscription,: as =>: subscribable has_many: subscribers
,: through

ฉันจะยกตัวอย่างรหัสที่ล้มเหลวเป็นโพสต์แยกต่างหากในอนาคตอันใกล้นี้ :) มันจะช่วยให้ฉันไม่ต้องปวดหัวมากในการหาวิธีหลีกเลี่ยงข้อผิดพลาดนั้น
cgr
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.