2012-09-17 15 views
5

implemento una gerarchia di classi usando il modello della STIUtilizzando ambito, definito nel modello di genitore, al suo interno del bambino (modello STI)

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

class B < A 
end 

Il problema è che quando provo a chiamare qualcosa come:

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

Così sto ottenendo 5 oggetti di tipo a, che soddisfa la portata: aaa Ma ho bisogno di fare lo stesso con righe in cui type = "B"

c'è un modo per utilizzare gli ambiti da genitore, senza ridistribuirlo in child in pattern STI?

Grazie in anticipo

a cura

Ho appena parlato con il mio frind e mi ha mostrato una cosa importante. A in non la classe radice di STI. In realtà tutta la gerarchia sembra

class O < ActiveRecord::Base 
end 

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

class B < A 
end 

forse il motivo è nella gerarchia stessa? ...

risposta

2

Lei ha ragione che questo è il risultato della gerarchia multi-livello.

Il campo di applicazione dovrebbe funzionare come previsto se si ha un solo livello di eredità (cioè se A ereditato da ActiveRecord::Base invece di ereditare da O).

STI in Rails non funziona sempre come previsto una volta che si hanno classi intermedie.

Non sono sicuro che si tratti di un bug in Rails o solo il risultato di non essere fattibile per dedurre esattamente cosa dovrebbe essere fatto. Dovrò cercare di più.

Il problema di ambito che hai riscontrato è solo un esempio del comportamento imprevisto. Un altro esempio è che l'interrogazione della classe intermedia richiederà solo i tipi di classe di cui è a conoscenza, che potrebbero non includere tutte le sottoclassi a meno che non siano specificatamente richieste:

Vedere la seguente discussione per ulteriori informazioni, in particolare il post in il fondo per MatthewRudy: https://groups.google.com/forum/#!topic/hkror/iCg3kxXkxnA

Se si desidera continuare a utilizzare gli ambiti, invece di metodi di classe come suggerito da @Atastor, si può mettere l'ambito su O invece di A. Questo non è l'ideale poiché l'ambito potrebbe non essere applicabile a tutte le sottoclassi di O, ma sembra che Rails interroghi le classi corrette nella colonna type ed è una soluzione rapida.

1

vorrei passare ad usare un metodo di classe invece di un campo di applicazione, per esempio in classe A

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

e poi in classe B

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

Funziona, ma ho ancora curioso di sapere perchè il mio esempio non funziona come mi aspetto che – AntonTkachov

0

Prestare attenzione alle classi intermedie STI perché possono danneggiare l'oscilloscopio che si sta tentando.

Nel mio caso ho avuto:

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 

E il campo di applicazione è stato effettivamente compresa la Classe C e Classe D combinati.

Quindi, se avete STI in Rails Si prega di inserire gli scopi della classe base, non classi intermedie