2010-08-20 3 views
19

czego szukam zrobić, to mieć klasę bazową dla niektórych z moich modeli, które ma pewne zachowanie domyślne ActiveRecord:Rails ActiveRecord - dziedziczenie z klasy bazowej bez stołu

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 

Jednakże chcę ColorOption i FabricOption dla każdego z nich we własnych tabelach. NIE chcę używać STI ani tabeli dla klasy bazowej "Opcja". Jedynym sposobem, w jaki to zrobiłem, jest magia metaprogramowania, która nie jest dziedziczona. Ale zastanawiałem się, czy istnieje sposób, aby powiedzieć AR, że klasa bazowa nie potrzebuje tabeli. Jest tam tylko po to, by zachować dodatkowe zachowanie i umieścić pozostałe podklasy w swoim własnym stole, jak zwykle.

Dzięki Craig

Odpowiedz

17

Wygląda przypadku do modułu, który dołączyć.

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 

Więcej informacji: http://mediumexposure.com/multiple-table-inheritance-active-record/

+0

Tak, próbowałem modułu, ale moduł nie może zobaczyć aktywnych metod zapisu, takich jak has_many: products. Mówi, że metoda jest niezdefiniowana. – fregas

+0

Jak próbowałeś? Stephan –

+0

fregas: upewnij się, że zawiera wszystkie wywołania metod klas, takie jak 'has_many' lub walidacje wewnątrz metody' self.included' Stephan ma w swoim przykładzie –

46

Co chcesz jest klasa abstrakcyjna:

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 

mam pewne dodatkowe informacje o STI and #abstract_class na moim blogu.

+0

Nie próbowałem tego, ale wydaje się to również uzasadnione. – fregas

+0

Czy muszę ustawić nazwę tabeli, czy też AR może to właśnie sugerować? – fregas

+0

Wypróbuj bez. Nie potrafię odróżnić, jeśli będzie działać bez. –

5

Miałem podobny problem, ale chciałem także zmienić sposób, w jaki AR ustawiał nazwę tabeli dla moich modeli, na przykład model MyProject miałby nazwę tabeli "MY_PROJECT".

mam go osiągnąć poprzez utworzenie klasy abstrakcyjnej AR, jak @ FFrançois powiedział i odziedziczonej metody, gdzie jestem zmieniającej nazwę tabeli, na przykład:

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 

Teraz MyProject.table_name daje MY_PROJECT:)