2010-08-20 20 views
19

Quello che sto cercando di fare è avere una classe base per alcuni dei miei modelli che ha un certo comportamento predefinito ActiveRecord:Rails ActiveRecord - eredita da una classe base senza tavolo

class Option < ActiveRecord::Base 
    has_many :products 

    def some_method 
    #stuff 
    end 

    #etc..etc.. 
end 

class ColorOption < Option 
    #stuff... 
end 


class FabricOption < Option 
    #stuff... 
end 

Tuttavia, voglio ColorOption e FabricOption si trovano ciascuno nelle proprie tabelle. NON voglio usare STI o avere una tabella per la classe di base "Opzione". L'unico modo per farlo funzionare è con una magia di metaprogrammazione non ereditaria. Ma mi chiedevo se c'era un modo per dire ad AR che la classe base non ha bisogno di un tavolo. È solo lì per un comportamento in più e per mettere le altre sottoclassi nella propria tabella come al solito.

Grazie, Craig

risposta

17

Sembra come un caso per un modulo che si include.

module Option 
    def self.included(base) 
    base.has_many :products 
    end 

    # other instance methods 
end 

class ColorOption < ActiveRecord::Base 
    include Option 
    set_table_name '???' # unless ColorOption/FabricOption have same table -> move to Option module 

    #stuff... 

end 


class FabricOption < Option 
    include Option 
    set_table_name '???' # unless ColorOption/FabricOption have same table -> move to Option module 

    #stuff... 
end 

Maggiori informazioni: http://mediumexposure.com/multiple-table-inheritance-active-record/

+0

sì ho provato il modulo, ma il modulo non può vedere i metodi di registrazione attivi come has_many: prodotti. Dice che il metodo non è definito. – fregas

+0

Come hai provato? Stephan –

+0

fregas: assicurati di includere qualsiasi chiamata al metodo di classe, come 'has_many' o convalide all'interno del metodo' self.included' Stephan ha nel suo esempio –

46

quello che vuoi è una classe astratta:

class Option < ActiveRecord::Base 
    self.abstract_class = true 
end 

class ColorOption < Option 
    set_table_name "color_options" 
end 

class FabricOption < Option 
    set_table_name "fabric_options" 
end 

Ho qualche informazione in più su STI and #abstract_class sul mio blog.

+0

havent provato questo, ma questo sembra ragionevole anche – fregas

+0

devo impostare il nome della tabella, o AR può solo dedurre che? – fregas

+0

Provalo senza. Non posso dire fuori mano se funzionerà senza. –

5

Avevo un problema simile, ma volevo anche cambiare il modo in cui AR stava impostando table_name per i miei modelli, che ad esempio il modello MyProject avrebbe il nome di tabella "MY_PROJECT".

che ho raggiunto con la creazione di classe AR astratta, come @ FFrançois detto, e con metodo ereditato, dove sto cambiando il nome della tabella, in questo modo:

class MyModel < ActiveRecord::Base 
    self.abstract_class = true 

    def self.inherited(subclass) 
    subclass.table_name = subclass.name.underscore.upcase 
    end 
end 

class MyProject < MyModel 
end 

Ora MyProject.table_name dà MY_PROJECT:)

Problemi correlati