2012-02-11 4 views
5

Ho un modulo che sto anche in diversi modelli con questo contenuto:Come utilizzare sempre la classe base e ignorare STI in Rails?

self.class.find_by_foo(bar) 

Tutto andava bene fino a quando ho iniziato ad usare STI. Quella linea dovrebbe sempre generare la query

select * from table where foo=bar" 

e non

select * from table where foo=bar AND type="Whatever" 

C'è un modo semplice per evitarlo?

Ho pensato a due soluzioni. Salendo la gerarchia delle classi fino a quando ho trovato la parte superiore più di classe prima di ActiveRecord::Base o funzionare la domanda a mano, come:

self.class.find_by_sql("select * from #{self.class.table_name} where foo=bar") 

Non mi piacciono entrambe le soluzioni. C'è uno migliore?

risposta

2

Fino c'è una risposta migliore, sto usando questo codice per trovare la classe di base della catena STI:

klass = self.class 
self.class.ancestors.each do |k| 
    if k == ActiveRecord::Base 
    break # we reached the bottom of this barrel 
    end 
    if k.is_a? Class 
    klass = k 
    end 
end 
19

In primo luogo, si può sempre ottenere alla classe di base con le BASE_CLASS metodo:

self.class.base_class.find_by_foo(bar) 

Tuttavia, nell'esempio sopra riportato, non è necessario accedere alla classe base. Si può solo effettuare le seguenti operazioni e Rails conoscerà il nome della tabella corretta:

self.class.where(:foo => bar) 

ci sono in realtà molto pochi casi in cui è necessario accedere alla classe di base.

+0

In Rails 4 'self.class' ha restituito inaspettatamente la classe genitore degli oggetti, in Rails 5' self.class' restituisce, come escluso, la classe dei modelli. 'self.class.base_class' può essere usato per ottenere la classe genitore. – Kris