ActiveRecord, has_many: through ve Polymorphic Associations


117

Millet,

Bunu doğru anladığımdan emin olmak istiyorum. Ve lütfen buradaki miras durumunu göz ardı edin (SentientBeing), bunun yerine has_many'deki polimorfik modellere odaklanmaya çalışın: ilişkiler yoluyla. Bununla birlikte, şunu düşünün ...

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

Mükemmel bir dünyada, bir Widget ve bir Kişi verildiğinde, şöyle bir şey yapmak isterim:

widget.people << my_person

Ancak, bunu yaptığımda, 'gruplayıcı'nın' türünün 'widget_groupings içinde her zaman boş olduğunu fark ettim. Ancak, aşağıdaki gibi bir şey yaparsam:

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

Sonra normalde beklediğim gibi işler. Bunun polimorfik olmayan çağrışımlarla gerçekleştiğini hiç görmediğimi sanmıyorum ve sadece bunun bu kullanım durumuna özgü bir şey olup olmadığını veya potansiyel olarak bir hataya bakıp bakmadığımı bilmek istedim.

Herhangi bir yardım için teşekkürler!

Yanıtlar:


162

Bu işlevi bozan bilinen bir Rails 3.1.1 sorunu vardır. Bu sorunu yaşıyorsanız, önce yükseltmeyi deneyin, 3.1.2'de düzeltilmiştir.

Çok yakınsın Sorun şu ki: kaynak seçeneğini kötüye kullanıyorsunuz. : kaynak polimorfik aitlik ilişkisine işaret etmelidir. O zaman yapmanız gereken tek şey, tanımlamaya çalıştığınız ilişki için kaynak_tipini belirtmektir.

Widget modelinde yapılan bu düzeltme, tam olarak aradığınız şeyi yapmanıza izin vermelidir.

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

Aman tanrım, o kadar açık ki, tam üzerine cam yaptığıma inanamıyorum. Teşekkürler EmFi!
Cory

Sorun değil, sanırım ilk karşılaştığımda bunun nasıl yapılacağı konusunda yaklaşık bir gün acı çektim. Bir öğreticiyi / kitabı takip etmeyi içermeyen Rails'de yapmaya çalıştığım ilk şeylerden biri olmasına yardımcı olmadım.
EmFi

1
Scotkf'un işaret ettiği gibi, ActiveRecord 3.1.1'de bu davranışı engelleyen bir gerileme vardır. 3.1.2 sürümüne yükseltme, bu çözümün çalışmasına izin verecektir.
EmFi

6
@Shtirlic'in bahsettiği ile aynı şey. Karma sonuç kümeniz olması için kaynak_türü belirtmemenin bir yolu var mı? Biri bunu çözdüyse, nasıl olduğunu bilmek isterim.
Damon Aw

3
Halen Rails 4.2.0'dan itibaren çalışmaktadır. Ancak, bu günlerde bunu source_type ve iki ayrı ilişkilendirme olmadan gerçekleştirmenin bir yolu var mı?
Emeka

3

Yukarıda belirtildiği gibi, bu, kaynak üzerindeki bir hata nedeniyle raylar 3.1.1 ile çalışmaz, ancak Rails 3.1.2'de düzeltilmiştir.


-4

çoktur: through ve polymorphic birlikte çalışmaz. Bunlara doğrudan erişmeye çalışırsanız, bir hata vermesi gerekir. Yanılmıyorsam, widget.people ve push rutinini elle yazmanız gerekir.

Bunun bir hata olduğunu düşünmüyorum, henüz uygulanmamış bir şey. Bunu özellikte gördüğümüzü tahmin ediyorum, çünkü herkesin kullanabileceği bir vakası var.


6
Birlikte çalışıyorlar. Örneğin: has_many: subscriptions,: as =>: subscribable has_many: subscribers
,:

Başarısız olan kodumun bir örneğini yakın gelecekte ayrı bir gönderi olarak atacağım :) Bu hatayı nasıl atlayacağımı bulmak beni çok fazla baş ağrısından kurtarırdı.
cgr
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.