2012-06-20 15 views
6

STI kullanırken raylar 3 ile bir has_many ilişkisinden koleksiyon alınırken garip bir davranış alıyorum. Ben:Raylar Alt sınıflarla STI ilişkilendirme

class Branch < ActiveRecord::Base 
    has_many :employees, class_name: 'User::Employee' 
    has_many :admins, class_name: 'User::BranchAdmin' 
end 

class User < ActiveRecord::Base 
end 

class User::Employee < User 
    belongs_to :branch 
end 

class User::BranchAdmin < User::Employee 
end 

istenilen davranış olduğunu dal yöneticileri dahil branch.employees döner tüm çalışanlar. Bu konsoldan çıktı şube yöneticileri yalnızca branch.admins olarak erişildiğini de bu koleksiyon altındaki 'yüklü' gibi görünüyor geçerli:

Branch.first.employees.count 
=> 2 

Branch.first.admins.count 
=> 1 

Branch.first.employees.count 
=> 3 

Bu oluşturulan SQL görülebilir, ilk kez:

SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee') AND "users"."branch_id" = 1 

ve ikinci zamanı: sadece belirterek bu sorunu çözebilir

SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee', 'User::BranchAdmin') AND "users"."branch_id" = 1 

:

class Branch < ActiveRecord::Base 
    has_many :employees, class_name: 'User' 
    has_many :admins, class_name: 'User::BranchAdmin' 
end 

hepsi branch_id gelen bulunabilir ama sonra sınıf User varsayılan yapar branch.employees.build yapmak istiyorum ve bir yere yazın sütununda kesmek zorunda kontrol işlemindeki sorun yaratır çünkü. Bunun için şu an var olan:

has_many :employees, class_name: 'User::Employee', 
    finder_sql: Proc.new{ 
     %Q(SELECT users.* FROM users WHERE users.type IN   ('User::Employee','User::BranchAdmin') AND users.branch_id = #{id}) 
    }, 
    counter_sql: Proc.new{ 
     %Q(SELECT COUNT(*) FROM "users" WHERE "users"."type" IN ('User::Employee', 'User::BranchAdmin') AND "users"."branch_id" = #{id}) 
    } 

Ancak mümkünse bunu önlemek isterim. Herkes, herhangi bir fikir?

DÜZENLEME: aile birlikleri bu kullanmayan ve bu nedenle organisation.employeeshas_many :employees, through: :branches yine sadece seçiminde User::Employee sınıf içerecektir görünüyor çünkü

finder_sql ve counter_sql gerçekten benim için çözülmüş değil.

cevap

17

Temel olarak, sorun yalnızca sınıfların gerektiği gibi yüklendiği geliştirme ortamında bulunmaktadır. (Üretimde, sınıflar yüklenip hazır bulundurulur.)

sorun değil ilk Employee.find çalıştırdığınızda Admins vb çağrı Employee bir tür olduğu henüz gördükten tercüman nedeniyle geliyor.

Bu, birden fazla düzey derin olan bir model sınıfların her kullanımla olur, ancak yalnızca dev-modunda (daha sonra IN ('User::Employee', 'User::BranchAdmin') kullandığına dikkat edin). Alt sınıflar her zaman üst sıradaki hiyerarşisini otomatik olarak yükler. Temel sınıflar çocuk hiyerarşiklerini otomatik olarak yüklemez.

Hack düzeltme:

Açıkça temel sınıf rb dosyadan tüm Çocuğunuz sınıfları isteyerek dev modunda doğru davranış zorlayabilir.

+2

Bu harika bir fırsat, teşekkürler. Model yapısı her halükarda değişti, bu yüzden problem ortadan kalktı ama ben bunun çevrenin bir etkisi olduğunu düşündüğümü düşünmüyorum! –

2

:conditions kullanıyor musunuz?

Tercih ettiğim yöntem bu olurdu. Bunu yapmanın bir diğer yolu, polimorfik modellere varsayılan bir kapsam eklemek olabilir.

class User::BranchAdmin < User::Employee 
    default_scope where("type = ?", name) 
end 
+0

Koşulları kullanmayı denedim, ancak bununla da ilgili sorunlar yaşadım. Uygulamanın yapısı şimdi değişti bu yüzden bu konuda endişelenmenize gerek yoktu, bu raylar 3.2.7 sabitlenmiş olabilir. –

İlgili konular