2012-09-17 15 views
5

zaimplementować hierarchię klas przy użyciu STI wzorzecKorzystanie zakres zdefiniowany w modelu dominującego, w środku jest dziecko (STI wzór)

class A 
    scope :aaa, where([someField]:[someValue]) 
end 

class B < A 
end 

Problemem jest to, że gdy próbuję wywołać coś takiego:

B.limit(5).aaa 
=> SELECT "[table]".* FROM "[table]" WHERE "[table]"."type" IN ('A') AND ([someField] = [someValue]) LIMIT 5 

Więc ja dostaję 5 obiektów typu A, który spełnia zakres: aaa Ale muszę zrobić to samo z wierszy, gdzie type = „B”

Czy istnieje jakiś sposób, aby skorzystać z zakresów rodzic, bez przerabiania go na potomkach w układzie STI?

góry dzięki

EDITED

Właśnie rozmawialiśmy z moim frind a on pokazał mi jedną ważną rzecz. A nie jest klasą podstawową STI. W rzeczywistości cała hierarchia wygląda

class O < ActiveRecord::Base 
end 

class A < O 
    scope ..... ..... 
end 

class B < A 
end 

może powodem jest sama w sobie? Hierarchii ...

Odpowiedz

2

Masz rację, że jest to wynikiem hierarchii wielopoziomowego.

Zasięg działałby zgodnie z oczekiwaniami, gdybyś miał tylko jeden poziom dziedziczenia (np. Jeśli A odziedziczył po ActiveRecord::Base zamiast dziedziczyć po O).

Aplikacja STI w Railsach nie zawsze działa zgodnie z oczekiwaniami po utworzeniu klas pośrednich.

Nie jestem pewien, czy jest to błąd w Railsach, czy też po prostu nie można wywnioskować, co należy zrobić. Będę musiał zbadać to więcej.

Problem z zasięgiem, którego doświadczyłeś, jest tylko jednym z przykładów nieoczekiwanego zachowania. Innym przykładem jest to, że zapytanie do klasy pośredniej dotyczy tylko typów klas, o których jest świadomy, które mogą nie obejmować wszystkich swoich podklas, chyba że ich konkretnie potrzebujesz:

Zobacz następujący wątek, aby uzyskać więcej informacji, szczególnie na dno MatthewRudy: https://groups.google.com/forum/#!topic/hkror/iCg3kxXkxnA

Jeśli nadal chcesz używać zakresów zamiast metod klasowych zgodnie z sugestią @Aastastor, możesz umieścić zakres na O zamiast A. To nie jest idealne, ponieważ zakres może nie mieć zastosowania do każdej podklasy O, ale wydaje się, że powoduje, że Railsy wysyłają zapytania do poprawnych klas w kolumnie type i jest to szybkie rozwiązanie.

1

chciałbym przełączyć się za pomocą metody klasy zamiast zakresie, na przykład w klasie A

def self.aaa 
    A.where([someField]:[someValue]) 
end 

a potem w klasie B

def self.bbb 
    self.aaa.where("type = ?","B") 
end 
+0

To działa, ale nadal ciekawy dlaczego mój przykład nie działa jak mam się go spodziewać – AntonTkachov

0

Uważaj na klasy pośrednie STI, ponieważ może to zepsuć zakres, którego próbujesz.

W moim przypadku miałem:

class A < ActiveRecord 
blabla 
end 
class B < A 
scope :dates, ->(start_date, end_date) { where(:date => start_date..end_date) } 
end 
class C < B 
<call scope_dates> 
end 
class D < B 
<call scope_dates> 
end 

oraz zakres faktycznie w tym klasy C i klasy D w połączeniu.

Tak więc, jeśli masz STI w Rails Proszę umieścić zasięgów w klasie bazowej, a nie klasy pośrednie